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:
parent
b49d74d999
commit
e99cd56b6c
|
@ -10,7 +10,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/common"
|
"github.com/mitchellh/packer/common"
|
||||||
|
@ -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.")
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
auth, err := b.config.AccessConfig.Auth()
|
ec2conn := ec2.New(config)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ec2conn := ec2.New(auth, region)
|
|
||||||
|
|
||||||
wrappedCommand := func(command string) (string, error) {
|
wrappedCommand := func(command string) (string, error) {
|
||||||
return b.config.tpl.Process(
|
return b.config.tpl.Process(
|
||||||
|
|
|
@ -3,11 +3,12 @@ package chroot
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// StepAttachVolume attaches the previously created volume to an
|
// 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)
|
attachVolume := strings.Replace(device, "/xvd", "/sd", 1)
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Attaching the root volume to %s", attachVolume))
|
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 {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error attaching volume: %s", err)
|
err := fmt.Errorf("Error attaching volume: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -50,7 +55,7 @@ func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
StepState: state,
|
StepState: state,
|
||||||
Target: "attached",
|
Target: "attached",
|
||||||
Refresh: func() (interface{}, string, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
@ -60,7 +65,7 @@ func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
a := resp.Volumes[0].Attachments[0]
|
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 := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Detaching EBS volume...")
|
ui.Say("Detaching EBS volume...")
|
||||||
_, err := ec2conn.DetachVolume(s.volumeId)
|
_, err := ec2conn.DetachVolume(&ec2.DetachVolumeInput{VolumeID: &s.volumeId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error detaching EBS volume: %s", err)
|
return fmt.Errorf("Error detaching EBS volume: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -105,14 +110,14 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
|
||||||
StepState: state,
|
StepState: state,
|
||||||
Target: "detached",
|
Target: "detached",
|
||||||
Refresh: func() (interface{}, string, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
v := resp.Volumes[0]
|
v := resp.Volumes[0]
|
||||||
if len(v.Attachments) > 0 {
|
if len(v.Attachments) > 0 {
|
||||||
return v, v.Attachments[0].Status, nil
|
return v, *v.Attachments[0].State, nil
|
||||||
} else {
|
} else {
|
||||||
return v, "detached", nil
|
return v, "detached", nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package chroot
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"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...")
|
ui.Say("Checking the root device on source AMI...")
|
||||||
|
|
||||||
// It must be EBS-backed otherwise the build won't work
|
// 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.")
|
err := fmt.Errorf("The root device of the source AMI must be EBS-backed.")
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
|
|
@ -2,11 +2,12 @@ package chroot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"log"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// StepCreateVolume creates a new volume from the snapshot of the root
|
// 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)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
// Determine the root device snapshot
|
// 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
|
var rootDevice *ec2.BlockDeviceMapping
|
||||||
for _, device := range image.BlockDevices {
|
for _, device := range image.BlockDeviceMappings {
|
||||||
if device.DeviceName == image.RootDeviceName {
|
if device.DeviceName == image.RootDeviceName {
|
||||||
rootDevice = &device
|
rootDevice = device
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,12 +43,12 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Creating the root volume...")
|
ui.Say("Creating the root volume...")
|
||||||
createVolume := &ec2.CreateVolume{
|
createVolume := &ec2.CreateVolumeInput{
|
||||||
AvailZone: instance.AvailZone,
|
AvailabilityZone: instance.Placement.AvailabilityZone,
|
||||||
Size: rootDevice.VolumeSize,
|
Size: rootDevice.EBS.VolumeSize,
|
||||||
SnapshotId: rootDevice.SnapshotId,
|
SnapshotID: rootDevice.EBS.SnapshotID,
|
||||||
VolumeType: rootDevice.VolumeType,
|
VolumeType: rootDevice.EBS.VolumeType,
|
||||||
IOPS: rootDevice.IOPS,
|
IOPS: rootDevice.EBS.IOPS,
|
||||||
}
|
}
|
||||||
log.Printf("Create args: %#v", createVolume)
|
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
|
// 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)
|
log.Printf("Volume ID: %s", s.volumeId)
|
||||||
|
|
||||||
// Wait for the volume to become ready
|
// Wait for the volume to become ready
|
||||||
|
@ -69,13 +70,13 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
StepState: state,
|
StepState: state,
|
||||||
Target: "available",
|
Target: "available",
|
||||||
Refresh: func() (interface{}, string, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
v := resp.Volumes[0]
|
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 := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Deleting the created EBS volume...")
|
ui.Say("Deleting the created EBS volume...")
|
||||||
_, err := ec2conn.DeleteVolume(s.volumeId)
|
_, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeID: &s.volumeId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err))
|
ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,12 @@ package chroot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/aws"
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
"log"
|
"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.
|
// 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
|
// Get our own instance ID
|
||||||
ui.Say("Gathering information about this EC2 instance...")
|
ui.Say("Gathering information about this EC2 instance...")
|
||||||
instanceIdBytes, err := aws.GetMetaData("instance-id")
|
instanceIdBytes, err := common.GetInstanceMetaData("instance-id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error: %s", err)
|
log.Printf("Error: %s", err)
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
|
@ -33,7 +34,7 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
log.Printf("Instance ID: %s", instanceId)
|
log.Printf("Instance ID: %s", instanceId)
|
||||||
|
|
||||||
// Query the entire instance metadata
|
// 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 {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error getting instance data: %s", err)
|
err := fmt.Errorf("Error getting instance data: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
|
|
@ -3,12 +3,13 @@ package chroot
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mountPathData struct {
|
type mountPathData struct {
|
||||||
|
@ -59,9 +60,9 @@ func (s *StepMountDevice) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
return multistep.ActionHalt
|
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
|
deviceMount := device
|
||||||
if image.VirtualizationType == "hvm" {
|
if *image.VirtualizationType == "hvm" {
|
||||||
deviceMount = fmt.Sprintf("%s%d", device, 1)
|
deviceMount = fmt.Sprintf("%s%d", device, 1)
|
||||||
}
|
}
|
||||||
state.Put("deviceMount", deviceMount)
|
state.Put("deviceMount", deviceMount)
|
||||||
|
|
|
@ -3,7 +3,8 @@ package chroot
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"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 := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Registering the AMI...")
|
ui.Say("Registering the AMI...")
|
||||||
blockDevices := make([]ec2.BlockDeviceMapping, len(image.BlockDevices))
|
blockDevices := make([]*ec2.BlockDeviceMapping, len(image.BlockDeviceMappings))
|
||||||
for i, device := range image.BlockDevices {
|
for i, device := range image.BlockDeviceMappings {
|
||||||
newDevice := device
|
newDevice := device
|
||||||
if newDevice.DeviceName == image.RootDeviceName {
|
if newDevice.DeviceName == image.RootDeviceName {
|
||||||
newDevice.SnapshotId = snapshotId
|
newDevice.EBS.SnapshotID = &snapshotId
|
||||||
}
|
}
|
||||||
|
|
||||||
blockDevices[i] = newDevice
|
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
|
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
|
||||||
if config.AMIEnhancedNetworking {
|
if config.AMIEnhancedNetworking {
|
||||||
registerOpts.SriovNetSupport = "simple"
|
registerOpts.SRIOVNetSupport = aws.String("simple")
|
||||||
}
|
}
|
||||||
|
|
||||||
registerResp, err := ec2conn.RegisterImage(registerOpts)
|
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
|
// 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 := make(map[string]string)
|
||||||
amis[ec2conn.Region.Name] = registerResp.ImageId
|
amis[ec2conn.Config.Region] = *registerResp.ImageID
|
||||||
state.Put("amis", amis)
|
state.Put("amis", amis)
|
||||||
|
|
||||||
// Wait for the image to become ready
|
// Wait for the image to become ready
|
||||||
stateChange := awscommon.StateChangeConf{
|
stateChange := awscommon.StateChangeConf{
|
||||||
Pending: []string{"pending"},
|
Pending: []string{"pending"},
|
||||||
Target: "available",
|
Target: "available",
|
||||||
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, registerResp.ImageId),
|
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageID),
|
||||||
StepState: state,
|
StepState: state,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,18 +72,18 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {}
|
func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {}
|
||||||
|
|
||||||
func buildRegisterOpts(config *Config, image *ec2.Image, blockDevices []ec2.BlockDeviceMapping) *ec2.RegisterImage {
|
func buildRegisterOpts(config *Config, image *ec2.Image, blockDevices []*ec2.BlockDeviceMapping) *ec2.RegisterImageInput {
|
||||||
registerOpts := &ec2.RegisterImage{
|
registerOpts := &ec2.RegisterImageInput{
|
||||||
Name: config.AMIName,
|
Name: &config.AMIName,
|
||||||
Architecture: image.Architecture,
|
Architecture: image.Architecture,
|
||||||
RootDeviceName: image.RootDeviceName,
|
RootDeviceName: image.RootDeviceName,
|
||||||
BlockDevices: blockDevices,
|
BlockDeviceMappings: blockDevices,
|
||||||
VirtType: config.AMIVirtType,
|
VirtualizationType: &config.AMIVirtType,
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AMIVirtType != "hvm" {
|
if config.AMIVirtType != "hvm" {
|
||||||
registerOpts.KernelId = image.KernelId
|
registerOpts.KernelID = image.KernelID
|
||||||
registerOpts.RamdiskId = image.RamdiskId
|
registerOpts.RAMDiskID = image.RAMDiskID
|
||||||
}
|
}
|
||||||
|
|
||||||
return registerOpts
|
return registerOpts
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
package chroot
|
package chroot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/aws"
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testImage() ec2.Image {
|
func testImage() ec2.Image {
|
||||||
return ec2.Image{
|
return ec2.Image{
|
||||||
Id: "ami-abcd1234",
|
ImageID: aws.String("ami-abcd1234"),
|
||||||
Name: "ami_test_name",
|
Name: aws.String("ami_test_name"),
|
||||||
Architecture: "x86_64",
|
Architecture: aws.String("x86_64"),
|
||||||
KernelId: "aki-abcd1234",
|
KernelID: aws.String("aki-abcd1234"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,23 +24,23 @@ func TestStepRegisterAmi_buildRegisterOpts_pv(t *testing.T) {
|
||||||
|
|
||||||
image := testImage()
|
image := testImage()
|
||||||
|
|
||||||
blockDevices := []ec2.BlockDeviceMapping{}
|
blockDevices := []*ec2.BlockDeviceMapping{}
|
||||||
|
|
||||||
opts := buildRegisterOpts(&config, &image, blockDevices)
|
opts := buildRegisterOpts(&config, &image, blockDevices)
|
||||||
|
|
||||||
expected := config.AMIVirtType
|
expected := config.AMIVirtType
|
||||||
if opts.VirtType != expected {
|
if *opts.VirtualizationType != expected {
|
||||||
t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, opts.VirtType)
|
t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, *opts.VirtualizationType)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = config.AMIName
|
expected = config.AMIName
|
||||||
if opts.Name != expected {
|
if *opts.Name != expected {
|
||||||
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, opts.Name)
|
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, *opts.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = image.KernelId
|
expected = *image.KernelID
|
||||||
if opts.KernelId != expected {
|
if *opts.KernelID != expected {
|
||||||
t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, opts.KernelId)
|
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()
|
image := testImage()
|
||||||
|
|
||||||
blockDevices := []ec2.BlockDeviceMapping{}
|
blockDevices := []*ec2.BlockDeviceMapping{}
|
||||||
|
|
||||||
opts := buildRegisterOpts(&config, &image, blockDevices)
|
opts := buildRegisterOpts(&config, &image, blockDevices)
|
||||||
|
|
||||||
expected := config.AMIVirtType
|
expected := config.AMIVirtType
|
||||||
if opts.VirtType != expected {
|
if *opts.VirtualizationType != expected {
|
||||||
t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, opts.VirtType)
|
t.Fatalf("Unexpected VirtType value: expected %s got %s\n", expected, *opts.VirtualizationType)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = config.AMIName
|
expected = config.AMIName
|
||||||
if opts.Name != expected {
|
if *opts.Name != expected {
|
||||||
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, opts.Name)
|
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, *opts.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = ""
|
if opts.KernelID != nil {
|
||||||
if opts.KernelId != expected {
|
t.Fatalf("Unexpected KernelId value: expected nil got %s\n", *opts.KernelID)
|
||||||
t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, opts.KernelId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
@ -25,9 +25,12 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
volumeId := state.Get("volume_id").(string)
|
volumeId := state.Get("volume_id").(string)
|
||||||
|
|
||||||
ui.Say("Creating snapshot...")
|
ui.Say("Creating snapshot...")
|
||||||
createSnapResp, err := ec2conn.CreateSnapshot(
|
description := fmt.Sprintf("Packer: %s", time.Now().String())
|
||||||
volumeId,
|
|
||||||
fmt.Sprintf("Packer: %s", time.Now().String()))
|
createSnapResp, err := ec2conn.CreateSnapshot(&ec2.CreateSnapshotInput{
|
||||||
|
VolumeID: &volumeId,
|
||||||
|
Description: &description,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error creating snapshot: %s", err)
|
err := fmt.Errorf("Error creating snapshot: %s", err)
|
||||||
state.Put("error", 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
|
// 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))
|
ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId))
|
||||||
|
|
||||||
// Wait for the snapshot to be ready
|
// Wait for the snapshot to be ready
|
||||||
|
@ -45,7 +48,7 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
StepState: state,
|
StepState: state,
|
||||||
Target: "completed",
|
Target: "completed",
|
||||||
Refresh: func() (interface{}, string, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
@ -55,7 +58,7 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := resp.Snapshots[0]
|
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)
|
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
ui.Say("Removing snapshot since we cancelled or halted...")
|
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 {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error: %s", err))
|
ui.Error(fmt.Sprintf("Error: %s", err))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,13 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/aws"
|
"io/ioutil"
|
||||||
"github.com/mitchellh/packer/packer"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/aws"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccessConfig is for common configuration related to AWS access
|
// AccessConfig is for common configuration related to AWS access
|
||||||
|
@ -16,37 +19,48 @@ type AccessConfig struct {
|
||||||
Token string `mapstructure:"token"`
|
Token string `mapstructure:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth returns a valid aws.Auth object for access to AWS services, or
|
// Config returns a valid aws.Config object for access to AWS services, or
|
||||||
// an error if the authentication couldn't be resolved.
|
// an error if the authentication and region couldn't be resolved
|
||||||
func (c *AccessConfig) Auth() (aws.Auth, error) {
|
func (c *AccessConfig) Config() (*aws.Config, error) {
|
||||||
auth, err := aws.GetAuth(c.AccessKey, c.SecretKey)
|
credsProvider := aws.DetectCreds(c.AccessKey, c.SecretKey, c.Token)
|
||||||
if err == nil {
|
|
||||||
// Store the accesskey and secret that we got...
|
creds, err := credsProvider.Credentials()
|
||||||
c.AccessKey = auth.AccessKey
|
if err != nil {
|
||||||
c.SecretKey = auth.SecretKey
|
return nil, err
|
||||||
c.Token = auth.Token
|
|
||||||
}
|
|
||||||
if c.Token != "" {
|
|
||||||
auth.Token = c.Token
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// Region returns the aws.Region object for access to AWS services, requesting
|
||||||
// the region from the instance metadata if possible.
|
// the region from the instance metadata if possible.
|
||||||
func (c *AccessConfig) Region() (aws.Region, error) {
|
func (c *AccessConfig) Region() (string, error) {
|
||||||
if c.RawRegion != "" {
|
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 {
|
if err != nil {
|
||||||
return aws.Region{}, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
region := strings.TrimRightFunc(string(md), unicode.IsLetter)
|
region := strings.TrimRightFunc(string(md), unicode.IsLetter)
|
||||||
return aws.Regions[region], nil
|
return region, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
|
func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
|
@ -75,7 +89,7 @@ func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.RawRegion != "" {
|
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))
|
errs = append(errs, fmt.Errorf("Unknown region: %s", c.RawRegion))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,3 +100,24 @@ func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package common
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/aws"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,7 +80,7 @@ func (c *AMIConfig) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
regionSet[region] = struct{}{}
|
regionSet[region] = struct{}{}
|
||||||
|
|
||||||
// Verify the region is real
|
// 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))
|
errs = append(errs, fmt.Errorf("Unknown region: %s", region))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/aws"
|
"github.com/awslabs/aws-sdk-go/aws"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -67,8 +67,17 @@ func (a *Artifact) Destroy() error {
|
||||||
|
|
||||||
for region, imageId := range a.Amis {
|
for region, imageId := range a.Amis {
|
||||||
log.Printf("Deregistering image ID (%s) from region (%s)", imageId, region)
|
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)
|
errors = append(errors, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@ package common
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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"
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,21 +26,29 @@ type BlockDevices struct {
|
||||||
LaunchMappings []BlockDevice `mapstructure:"launch_block_device_mappings"`
|
LaunchMappings []BlockDevice `mapstructure:"launch_block_device_mappings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildBlockDevices(b []BlockDevice) []ec2.BlockDeviceMapping {
|
func buildBlockDevices(b []BlockDevice) []*ec2.BlockDeviceMapping {
|
||||||
var blockDevices []ec2.BlockDeviceMapping
|
var blockDevices []*ec2.BlockDeviceMapping
|
||||||
|
|
||||||
for _, blockDevice := range b {
|
for _, blockDevice := range b {
|
||||||
blockDevices = append(blockDevices, ec2.BlockDeviceMapping{
|
ebsBlockDevice := &ec2.EBSBlockDevice{
|
||||||
DeviceName: blockDevice.DeviceName,
|
SnapshotID: &blockDevice.SnapshotId,
|
||||||
VirtualName: blockDevice.VirtualName,
|
Encrypted: &blockDevice.Encrypted,
|
||||||
SnapshotId: blockDevice.SnapshotId,
|
IOPS: &blockDevice.IOPS,
|
||||||
VolumeType: blockDevice.VolumeType,
|
VolumeType: &blockDevice.VolumeType,
|
||||||
VolumeSize: blockDevice.VolumeSize,
|
VolumeSize: &blockDevice.VolumeSize,
|
||||||
DeleteOnTermination: blockDevice.DeleteOnTermination,
|
DeleteOnTermination: &blockDevice.DeleteOnTermination,
|
||||||
IOPS: blockDevice.IOPS,
|
}
|
||||||
NoDevice: blockDevice.NoDevice,
|
mapping := &ec2.BlockDeviceMapping{
|
||||||
Encrypted: blockDevice.Encrypted,
|
EBS: ebsBlockDevice,
|
||||||
})
|
DeviceName: &blockDevice.DeviceName,
|
||||||
|
VirtualName: &blockDevice.VirtualName,
|
||||||
|
}
|
||||||
|
|
||||||
|
if blockDevice.NoDevice {
|
||||||
|
mapping.NoDevice = aws.String("")
|
||||||
|
}
|
||||||
|
|
||||||
|
blockDevices = append(blockDevices, mapping)
|
||||||
}
|
}
|
||||||
return blockDevices
|
return blockDevices
|
||||||
}
|
}
|
||||||
|
@ -89,10 +98,10 @@ func (b *BlockDevices) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BlockDevices) BuildAMIDevices() []ec2.BlockDeviceMapping {
|
func (b *BlockDevices) BuildAMIDevices() []*ec2.BlockDeviceMapping {
|
||||||
return buildBlockDevices(b.AMIMappings)
|
return buildBlockDevices(b.AMIMappings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BlockDevices) BuildLaunchDevices() []ec2.BlockDeviceMapping {
|
func (b *BlockDevices) BuildLaunchDevices() []*ec2.BlockDeviceMapping {
|
||||||
return buildBlockDevices(b.LaunchMappings)
|
return buildBlockDevices(b.LaunchMappings)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/aws"
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBlockDevice(t *testing.T) {
|
func TestBlockDevice(t *testing.T) {
|
||||||
|
@ -23,13 +25,16 @@ func TestBlockDevice(t *testing.T) {
|
||||||
},
|
},
|
||||||
|
|
||||||
Result: &ec2.BlockDeviceMapping{
|
Result: &ec2.BlockDeviceMapping{
|
||||||
DeviceName: "/dev/sdb",
|
DeviceName: aws.String("/dev/sdb"),
|
||||||
VirtualName: "ephemeral0",
|
VirtualName: aws.String("ephemeral0"),
|
||||||
SnapshotId: "snap-1234",
|
EBS: &ec2.EBSBlockDevice{
|
||||||
VolumeType: "standard",
|
Encrypted: aws.Boolean(false),
|
||||||
VolumeSize: 8,
|
SnapshotID: aws.String("snap-1234"),
|
||||||
DeleteOnTermination: true,
|
VolumeType: aws.String("standard"),
|
||||||
IOPS: 1000,
|
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},
|
LaunchMappings: []BlockDevice{*tc.Config},
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := []ec2.BlockDeviceMapping{*tc.Result}
|
expected := []*ec2.BlockDeviceMapping{tc.Result}
|
||||||
|
got := blockDevices.BuildAMIDevices()
|
||||||
if !reflect.DeepEqual(expected, blockDevices.BuildAMIDevices()) {
|
if !reflect.DeepEqual(expected, got) {
|
||||||
t.Fatalf("bad: %#v", expected)
|
t.Fatalf("bad: %#v", expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go.crypto/ssh"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"time"
|
"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
|
// 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++ {
|
for j := 0; j < 2; j++ {
|
||||||
var host string
|
var host string
|
||||||
i := state.Get("instance").(*ec2.Instance)
|
i := state.Get("instance").(*ec2.Instance)
|
||||||
if i.VpcId != "" {
|
if *i.VPCID != "" {
|
||||||
if i.PublicIpAddress != "" && !private {
|
if *i.PublicIPAddress != "" && !private {
|
||||||
host = i.PublicIpAddress
|
host = *i.PublicIPAddress
|
||||||
} else {
|
} else {
|
||||||
host = i.PrivateIpAddress
|
host = *i.PrivateIPAddress
|
||||||
}
|
}
|
||||||
} else if i.DNSName != "" {
|
} else if *i.PublicDNSName != "" {
|
||||||
host = i.DNSName
|
host = *i.PublicDNSName
|
||||||
}
|
}
|
||||||
|
|
||||||
if host != "" {
|
if host != "" {
|
||||||
return fmt.Sprintf("%s:%d", host, port), nil
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.Reservations) == 0 || len(r.Reservations[0].Instances) == 0 {
|
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])
|
state.Put("instance", &r.Reservations[0].Instances[0])
|
||||||
|
|
|
@ -3,13 +3,15 @@ package common
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"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
|
// StateRefreshFunc is a function type used for StateChangeConf that is
|
||||||
|
@ -36,9 +38,11 @@ type StateChangeConf struct {
|
||||||
// an AMI for state changes.
|
// an AMI for state changes.
|
||||||
func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
|
func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
|
||||||
return func() (interface{}, string, error) {
|
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 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.
|
// Set this to nil as if we didn't find anything.
|
||||||
resp = nil
|
resp = nil
|
||||||
} else if isTransientNetworkError(err) {
|
} else if isTransientNetworkError(err) {
|
||||||
|
@ -57,7 +61,7 @@ func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
i := resp.Images[0]
|
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.
|
// an EC2 instance.
|
||||||
func InstanceStateRefreshFunc(conn *ec2.EC2, i *ec2.Instance) StateRefreshFunc {
|
func InstanceStateRefreshFunc(conn *ec2.EC2, i *ec2.Instance) StateRefreshFunc {
|
||||||
return func() (interface{}, string, error) {
|
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 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.
|
// Set this to nil as if we didn't find anything.
|
||||||
resp = nil
|
resp = nil
|
||||||
} else if isTransientNetworkError(err) {
|
} else if isTransientNetworkError(err) {
|
||||||
|
@ -85,8 +91,8 @@ func InstanceStateRefreshFunc(conn *ec2.EC2, i *ec2.Instance) StateRefreshFunc {
|
||||||
return nil, "", nil
|
return nil, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
i = &resp.Reservations[0].Instances[0]
|
i = resp.Reservations[0].Instances[0]
|
||||||
return i, i.State.Name, nil
|
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.
|
// a spot request for state changes.
|
||||||
func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefreshFunc {
|
func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefreshFunc {
|
||||||
return func() (interface{}, string, error) {
|
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 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.
|
// Set this to nil as if we didn't find anything.
|
||||||
resp = nil
|
resp = nil
|
||||||
} else if isTransientNetworkError(err) {
|
} 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
|
// Sometimes AWS has consistency issues and doesn't see the
|
||||||
// SpotRequest. Return an empty state.
|
// SpotRequest. Return an empty state.
|
||||||
return nil, "", nil
|
return nil, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
i := resp.SpotRequestResults[0]
|
i := resp.SpotInstanceRequests[0]
|
||||||
return i, i.State, nil
|
return i, *i.State, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,14 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepAMIRegionCopy struct {
|
type StepAMIRegionCopy struct {
|
||||||
|
@ -17,7 +20,7 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
amis := state.Get("amis").(map[string]string)
|
amis := state.Get("amis").(map[string]string)
|
||||||
ami := amis[ec2conn.Region.Name]
|
ami := amis[ec2conn.Config.Region]
|
||||||
|
|
||||||
if len(s.Regions) == 0 {
|
if len(s.Regions) == 0 {
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
|
@ -34,8 +37,7 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
go func(region string) {
|
go func(region string) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
id, err := amiRegionCopy(state, ec2conn.Auth, ami,
|
id, err := amiRegionCopy(state, ec2conn.Config.Credentials, ami, region, ec2conn.Config.Region)
|
||||||
aws.Regions[region], ec2conn.Region)
|
|
||||||
|
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
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
|
// amiRegionCopy does a copy for the given AMI to the target region and
|
||||||
// returns the resulting ID or error.
|
// returns the resulting ID or error.
|
||||||
func amiRegionCopy(state multistep.StateBag, auth aws.Auth, imageId string,
|
func amiRegionCopy(state multistep.StateBag, auth aws.CredentialsProvider, imageId string,
|
||||||
target aws.Region, source aws.Region) (string, error) {
|
target string, source string) (string, error) {
|
||||||
|
|
||||||
// Connect to the region where the AMI will be copied to
|
// Connect to the region where the AMI will be copied to
|
||||||
regionconn := ec2.New(auth, target)
|
config := &aws.Config{
|
||||||
resp, err := regionconn.CopyImage(&ec2.CopyImage{
|
Credentials: auth,
|
||||||
SourceRegion: source.Name,
|
Region: target,
|
||||||
SourceImageId: imageId,
|
}
|
||||||
|
regionconn := ec2.New(config)
|
||||||
|
resp, err := regionconn.CopyImage(&ec2.CopyImageInput{
|
||||||
|
SourceRegion: &source,
|
||||||
|
SourceImageID: &imageId,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Error Copying AMI (%s) to region (%s): %s",
|
return "", fmt.Errorf("Error Copying AMI (%s) to region (%s): %s",
|
||||||
imageId, target.Name, err)
|
imageId, target, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateChange := StateChangeConf{
|
stateChange := StateChangeConf{
|
||||||
Pending: []string{"pending"},
|
Pending: []string{"pending"},
|
||||||
Target: "available",
|
Target: "available",
|
||||||
Refresh: AMIStateRefreshFunc(regionconn, resp.ImageId),
|
Refresh: AMIStateRefreshFunc(regionconn, *resp.ImageID),
|
||||||
StepState: state,
|
StepState: state,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := WaitForState(&stateChange); err != nil {
|
if _, err := WaitForState(&stateChange); err != nil {
|
||||||
return "", fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s",
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,9 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
@ -21,14 +22,20 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
for region, ami := range amis {
|
for region, ami := range amis {
|
||||||
ui.Say(fmt.Sprintf("Adding tags to AMI (%s)...", ami))
|
ui.Say(fmt.Sprintf("Adding tags to AMI (%s)...", ami))
|
||||||
|
|
||||||
var ec2Tags []ec2.Tag
|
var ec2Tags []*ec2.Tag
|
||||||
for key, value := range s.Tags {
|
for key, value := range s.Tags {
|
||||||
ui.Message(fmt.Sprintf("Adding tag: \"%s\": \"%s\"", key, value))
|
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])
|
regionconn := ec2.New(&aws.Config{
|
||||||
_, err := regionconn.CreateTags([]string{ami}, ec2Tags)
|
Credentials: ec2conn.Config.Credentials,
|
||||||
|
Region: region,
|
||||||
|
})
|
||||||
|
_, err := regionconn.CreateTags(&ec2.CreateTagsInput{
|
||||||
|
Resources: []*string{&ami},
|
||||||
|
Tags: ec2Tags,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error adding tags to AMI (%s): %s", ami, err)
|
err := fmt.Errorf("Error adding tags to AMI (%s): %s", ami, err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
|
|
@ -2,12 +2,13 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepKeyPair struct {
|
type StepKeyPair struct {
|
||||||
|
@ -39,7 +40,7 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.KeyPairName))
|
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 {
|
if err != nil {
|
||||||
state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err))
|
state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err))
|
||||||
return multistep.ActionHalt
|
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
|
// Set some state data for use in future steps
|
||||||
state.Put("keyPair", s.keyName)
|
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
|
// If we're in debug mode, output the private key to the working
|
||||||
// directory.
|
// directory.
|
||||||
|
@ -64,7 +65,7 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
// Write the key out
|
// 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))
|
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
@ -91,7 +92,7 @@ func (s *StepKeyPair) Cleanup(state multistep.StateBag) {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Deleting temporary keypair...")
|
ui.Say("Deleting temporary keypair...")
|
||||||
_, err := ec2conn.DeleteKeyPair(s.keyName)
|
_, err := ec2conn.DeleteKeyPair(&ec2.DeleteKeyPairInput{KeyName: &s.keyName})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf(
|
ui.Error(fmt.Sprintf(
|
||||||
"Error cleaning up keypair. Please delete the key manually: %s", s.keyName))
|
"Error cleaning up keypair. Please delete the key manually: %s", s.keyName))
|
||||||
|
|
|
@ -2,8 +2,9 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"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.
|
// Construct the modify image attribute requests we're going to make.
|
||||||
// We need to make each separately since the EC2 API only allows changing
|
// We need to make each separately since the EC2 API only allows changing
|
||||||
// one type at a kind currently.
|
// one type at a kind currently.
|
||||||
options := make(map[string]*ec2.ModifyImageAttribute)
|
options := make(map[string]*ec2.ModifyImageAttributeInput)
|
||||||
if s.Description != "" {
|
if s.Description != "" {
|
||||||
options["description"] = &ec2.ModifyImageAttribute{
|
options["description"] = &ec2.ModifyImageAttributeInput{
|
||||||
Description: s.Description,
|
Description: &ec2.AttributeValue{Value: &s.Description},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.Groups) > 0 {
|
if len(s.Groups) > 0 {
|
||||||
options["groups"] = &ec2.ModifyImageAttribute{
|
groups := make([]*string, len(s.Groups))
|
||||||
AddGroups: s.Groups,
|
for i, g := range s.Groups {
|
||||||
|
groups[i] = &g
|
||||||
|
}
|
||||||
|
options["groups"] = &ec2.ModifyImageAttributeInput{
|
||||||
|
UserGroups: groups,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.Users) > 0 {
|
if len(s.Users) > 0 {
|
||||||
options["users"] = &ec2.ModifyImageAttribute{
|
users := make([]*string, len(s.Users))
|
||||||
AddUsers: s.Users,
|
for i, u := range s.Users {
|
||||||
|
users[i] = &u
|
||||||
|
}
|
||||||
|
options["users"] = &ec2.ModifyImageAttributeInput{
|
||||||
|
UserIDs: users,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.ProductCodes) > 0 {
|
if len(s.ProductCodes) > 0 {
|
||||||
options["product codes"] = &ec2.ModifyImageAttribute{
|
codes := make([]*string, len(s.ProductCodes))
|
||||||
ProductCodes: s.ProductCodes,
|
for i, c := range s.ProductCodes {
|
||||||
|
codes[i] = &c
|
||||||
|
}
|
||||||
|
options["product codes"] = &ec2.ModifyImageAttributeInput{
|
||||||
|
ProductCodes: codes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for region, ami := range amis {
|
for region, ami := range amis {
|
||||||
ui.Say(fmt.Sprintf("Modifying attributes on AMI (%s)...", ami))
|
ui.Say(fmt.Sprintf("Modifying attributes on AMI (%s)...", ami))
|
||||||
regionconn := ec2.New(ec2conn.Auth, aws.Regions[region])
|
regionconn := ec2.New(&aws.Config{
|
||||||
for name, opts := range options {
|
Credentials: ec2conn.Config.Credentials,
|
||||||
|
Region: region,
|
||||||
|
})
|
||||||
|
for name, input := range options {
|
||||||
ui.Message(fmt.Sprintf("Modifying: %s", name))
|
ui.Message(fmt.Sprintf("Modifying: %s", name))
|
||||||
_, err := regionconn.ModifyImageAttribute(ami, opts)
|
input.ImageID = &ami
|
||||||
|
_, err := regionconn.ModifyImageAttribute(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error modify AMI attributes: %s", err)
|
err := fmt.Errorf("Error modify AMI attributes: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
|
|
@ -7,7 +7,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"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/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
@ -29,15 +31,20 @@ type StepRunSourceInstance struct {
|
||||||
UserDataFile string
|
UserDataFile string
|
||||||
|
|
||||||
instance *ec2.Instance
|
instance *ec2.Instance
|
||||||
spotRequest *ec2.SpotRequestResult
|
spotRequest *ec2.SpotInstanceRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||||
keyName := state.Get("keyPair").(string)
|
keyName := state.Get("keyPair").(string)
|
||||||
securityGroupIds := state.Get("securityGroupIds").([]string)
|
tempSecurityGroupIds := state.Get("securityGroupIds").([]string)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
|
securityGroupIds := make([]*string, len(tempSecurityGroupIds))
|
||||||
|
for i, sg := range tempSecurityGroupIds {
|
||||||
|
securityGroupIds[i] = &sg
|
||||||
|
}
|
||||||
|
|
||||||
userData := s.UserData
|
userData := s.UserData
|
||||||
if s.UserDataFile != "" {
|
if s.UserDataFile != "" {
|
||||||
contents, err := ioutil.ReadFile(s.UserDataFile)
|
contents, err := ioutil.ReadFile(s.UserDataFile)
|
||||||
|
@ -49,13 +56,10 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||||
userData = string(contents)
|
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...")
|
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 {
|
if err != nil {
|
||||||
state.Put("error", fmt.Errorf("There was a problem with the source AMI: %s", err))
|
state.Put("error", fmt.Errorf("There was a problem with the source AMI: %s", err))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
@ -66,11 +70,11 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||||
return multistep.ActionHalt
|
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(
|
state.Put("error", fmt.Errorf(
|
||||||
"The provided source AMI has an invalid root device type.\n"+
|
"The provided source AMI has an invalid root device type.\n"+
|
||||||
"Expected '%s', got '%s'.",
|
"Expected '%s', got '%s'.",
|
||||||
s.ExpectedRootDevice, imageResp.Images[0].RootDeviceType))
|
s.ExpectedRootDevice, *imageResp.Images[0].RootDeviceType))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +86,11 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||||
|
|
||||||
// Detect the spot price
|
// Detect the spot price
|
||||||
startTime := time.Now().Add(-1 * time.Hour)
|
startTime := time.Now().Add(-1 * time.Hour)
|
||||||
resp, err := ec2conn.DescribeSpotPriceHistory(&ec2.DescribeSpotPriceHistory{
|
resp, err := ec2conn.DescribeSpotPriceHistory(&ec2.DescribeSpotPriceHistoryInput{
|
||||||
InstanceType: []string{s.InstanceType},
|
InstanceTypes: []*string{&s.InstanceType},
|
||||||
ProductDescription: []string{s.SpotPriceProduct},
|
ProductDescriptions: []*string{&s.SpotPriceProduct},
|
||||||
AvailabilityZone: s.AvailabilityZone,
|
AvailabilityZone: &s.AvailabilityZone,
|
||||||
StartTime: startTime,
|
StartTime: &startTime,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error finding spot price: %s", err)
|
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
|
var price float64
|
||||||
for _, history := range resp.History {
|
for _, history := range resp.SpotPriceHistory {
|
||||||
log.Printf("[INFO] Candidate spot price: %s", history.SpotPrice)
|
log.Printf("[INFO] Candidate spot price: %s", *history.SpotPrice)
|
||||||
current, err := strconv.ParseFloat(history.SpotPrice, 64)
|
current, err := strconv.ParseFloat(*history.SpotPrice, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[ERR] Error parsing spot price: %s", err)
|
log.Printf("[ERR] Error parsing spot price: %s", err)
|
||||||
continue
|
continue
|
||||||
|
@ -120,20 +124,33 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||||
var instanceId string
|
var instanceId string
|
||||||
|
|
||||||
if spotPrice == "" {
|
if spotPrice == "" {
|
||||||
runOpts := &ec2.RunInstances{
|
runOpts := &ec2.RunInstancesInput{
|
||||||
KeyName: keyName,
|
KeyName: &keyName,
|
||||||
ImageId: s.SourceAMI,
|
ImageID: &s.SourceAMI,
|
||||||
InstanceType: s.InstanceType,
|
InstanceType: &s.InstanceType,
|
||||||
UserData: []byte(userData),
|
UserData: &userData,
|
||||||
MinCount: 0,
|
MaxCount: aws.Long(1),
|
||||||
MaxCount: 0,
|
MinCount: aws.Long(1),
|
||||||
SecurityGroups: securityGroups,
|
IAMInstanceProfile: &ec2.IAMInstanceProfileSpecification{Name: &s.IamInstanceProfile},
|
||||||
IamInstanceProfile: s.IamInstanceProfile,
|
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
|
||||||
SubnetId: s.SubnetId,
|
Placement: &ec2.Placement{AvailabilityZone: &s.AvailabilityZone},
|
||||||
AssociatePublicIpAddress: s.AssociatePublicIpAddress,
|
|
||||||
BlockDevices: s.BlockDevices.BuildLaunchDevices(),
|
|
||||||
AvailZone: 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)
|
runResp, err := ec2conn.RunInstances(runOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error launching source instance: %s", err)
|
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())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
instanceId = runResp.Instances[0].InstanceId
|
instanceId = *runResp.Instances[0].InstanceID
|
||||||
} else {
|
} else {
|
||||||
ui.Message(fmt.Sprintf(
|
ui.Message(fmt.Sprintf(
|
||||||
"Requesting spot instance '%s' for: %s",
|
"Requesting spot instance '%s' for: %s",
|
||||||
s.InstanceType, spotPrice))
|
s.InstanceType, spotPrice))
|
||||||
|
|
||||||
runOpts := &ec2.RequestSpotInstances{
|
runSpotResp, err := ec2conn.RequestSpotInstances(&ec2.RequestSpotInstancesInput{
|
||||||
SpotPrice: spotPrice,
|
SpotPrice: &spotPrice,
|
||||||
KeyName: keyName,
|
LaunchSpecification: &ec2.RequestSpotLaunchSpecification{
|
||||||
ImageId: s.SourceAMI,
|
KeyName: &keyName,
|
||||||
InstanceType: s.InstanceType,
|
ImageID: &s.SourceAMI,
|
||||||
UserData: []byte(userData),
|
InstanceType: &s.InstanceType,
|
||||||
SecurityGroups: securityGroups,
|
UserData: &userData,
|
||||||
IamInstanceProfile: s.IamInstanceProfile,
|
SecurityGroupIDs: securityGroupIds,
|
||||||
SubnetId: s.SubnetId,
|
IAMInstanceProfile: &ec2.IAMInstanceProfileSpecification{Name: &s.IamInstanceProfile},
|
||||||
AssociatePublicIpAddress: s.AssociatePublicIpAddress,
|
SubnetID: &s.SubnetId,
|
||||||
BlockDevices: s.BlockDevices.BuildLaunchDevices(),
|
NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{
|
||||||
AvailZone: s.AvailabilityZone,
|
&ec2.InstanceNetworkInterfaceSpecification{AssociatePublicIPAddress: &s.AssociatePublicIpAddress},
|
||||||
}
|
},
|
||||||
runSpotResp, err := ec2conn.RequestSpotInstances(runOpts)
|
Placement: &ec2.SpotPlacement{AvailabilityZone: &s.AvailabilityZone},
|
||||||
|
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
|
||||||
|
},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error launching source spot instance: %s", err)
|
err := fmt.Errorf("Error launching source spot instance: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -168,44 +188,47 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
s.spotRequest = &runSpotResp.SpotRequestResults[0]
|
s.spotRequest = runSpotResp.SpotInstanceRequests[0]
|
||||||
|
|
||||||
spotRequestId := s.spotRequest.SpotRequestId
|
spotRequestId := s.spotRequest.SpotInstanceRequestID
|
||||||
ui.Message(fmt.Sprintf("Waiting for spot request (%s) to become active...", spotRequestId))
|
ui.Message(fmt.Sprintf("Waiting for spot request (%s) to become active...", *spotRequestId))
|
||||||
stateChange := StateChangeConf{
|
stateChange := StateChangeConf{
|
||||||
Pending: []string{"open"},
|
Pending: []string{"open"},
|
||||||
Target: "active",
|
Target: "active",
|
||||||
Refresh: SpotRequestStateRefreshFunc(ec2conn, spotRequestId),
|
Refresh: SpotRequestStateRefreshFunc(ec2conn, *spotRequestId),
|
||||||
StepState: state,
|
StepState: state,
|
||||||
}
|
}
|
||||||
_, err = WaitForState(&stateChange)
|
_, err = WaitForState(&stateChange)
|
||||||
if err != nil {
|
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)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
spotResp, err := ec2conn.DescribeSpotRequests([]string{spotRequestId}, nil)
|
|
||||||
|
spotResp, err := ec2conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{
|
||||||
|
SpotInstanceRequestIDs: []*string{spotRequestId},
|
||||||
|
})
|
||||||
if err != nil {
|
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)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
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 {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error finding source instance (%s): %s", instanceId, err)
|
err := fmt.Errorf("Error finding source instance (%s): %s", instanceId, err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
s.instance = &instanceResp.Reservations[0].Instances[0]
|
s.instance = instanceResp.Reservations[0].Instances[0]
|
||||||
ui.Message(fmt.Sprintf("Instance ID: %s", s.instance.InstanceId))
|
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{
|
stateChange := StateChangeConf{
|
||||||
Pending: []string{"pending"},
|
Pending: []string{"pending"},
|
||||||
Target: "running",
|
Target: "running",
|
||||||
|
@ -214,7 +237,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||||
}
|
}
|
||||||
latestInstance, err := WaitForState(&stateChange)
|
latestInstance, err := WaitForState(&stateChange)
|
||||||
if err != nil {
|
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)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
@ -222,29 +245,32 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||||
|
|
||||||
s.instance = latestInstance.(*ec2.Instance)
|
s.instance = latestInstance.(*ec2.Instance)
|
||||||
|
|
||||||
ec2Tags := make([]ec2.Tag, 1, len(s.Tags)+1)
|
ec2Tags := make([]*ec2.Tag, 1, len(s.Tags)+1)
|
||||||
ec2Tags[0] = ec2.Tag{"Name", "Packer Builder"}
|
ec2Tags[0] = &ec2.Tag{Key: aws.String("Name"), Value: aws.String("Packer Builder")}
|
||||||
for k, v := range s.Tags {
|
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 {
|
if err != nil {
|
||||||
ui.Message(
|
ui.Message(
|
||||||
fmt.Sprintf("Failed to tag a Name on the builder instance: %s", err))
|
fmt.Sprintf("Failed to tag a Name on the builder instance: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Debug {
|
if s.Debug {
|
||||||
if s.instance.DNSName != "" {
|
if *s.instance.PublicDNSName != "" {
|
||||||
ui.Message(fmt.Sprintf("Public DNS: %s", s.instance.DNSName))
|
ui.Message(fmt.Sprintf("Public DNS: %s", *s.instance.PublicDNSName))
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.instance.PublicIpAddress != "" {
|
if *s.instance.PublicIPAddress != "" {
|
||||||
ui.Message(fmt.Sprintf("Public IP: %s", s.instance.PublicIpAddress))
|
ui.Message(fmt.Sprintf("Public IP: %s", *s.instance.PublicIPAddress))
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.instance.PrivateIpAddress != "" {
|
if *s.instance.PrivateIPAddress != "" {
|
||||||
ui.Message(fmt.Sprintf("Private IP: %s", 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
|
// Cancel the spot request if it exists
|
||||||
if s.spotRequest != nil {
|
if s.spotRequest != nil {
|
||||||
ui.Say("Cancelling the spot request...")
|
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))
|
ui.Error(fmt.Sprintf("Error cancelling the spot request, may still be around: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
stateChange := StateChangeConf{
|
stateChange := StateChangeConf{
|
||||||
Pending: []string{"active", "open"},
|
Pending: []string{"active", "open"},
|
||||||
Refresh: SpotRequestStateRefreshFunc(ec2conn, s.spotRequest.SpotRequestId),
|
Refresh: SpotRequestStateRefreshFunc(ec2conn, *s.spotRequest.SpotInstanceRequestID),
|
||||||
Target: "cancelled",
|
Target: "cancelled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +308,7 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
|
||||||
if s.instance != nil {
|
if s.instance != nil {
|
||||||
|
|
||||||
ui.Say("Terminating the source AWS instance...")
|
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))
|
ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,14 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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/multistep"
|
||||||
"github.com/mitchellh/packer/common/uuid"
|
"github.com/mitchellh/packer/common/uuid"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepSecurityGroup struct {
|
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...")
|
ui.Say("Creating temporary security group for this instance...")
|
||||||
groupName := fmt.Sprintf("packer %s", uuid.TimeOrderedUUID())
|
groupName := fmt.Sprintf("packer %s", uuid.TimeOrderedUUID())
|
||||||
log.Printf("Temporary group name: %s", groupName)
|
log.Printf("Temporary group name: %s", groupName)
|
||||||
group := ec2.SecurityGroup{
|
group := &ec2.CreateSecurityGroupInput{
|
||||||
Name: groupName,
|
GroupName: &groupName,
|
||||||
Description: "Temporary group for Packer",
|
Description: aws.String("Temporary group for Packer"),
|
||||||
VpcId: s.VpcId,
|
VPCID: &s.VpcId,
|
||||||
}
|
}
|
||||||
groupResp, err := ec2conn.CreateSecurityGroup(group)
|
groupResp, err := ec2conn.CreateSecurityGroup(group)
|
||||||
if err != nil {
|
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
|
// Set the group ID so we can delete it later
|
||||||
s.createdGroupId = groupResp.Id
|
s.createdGroupId = *groupResp.GroupID
|
||||||
|
|
||||||
// Authorize the SSH access
|
// Authorize the SSH access for the security group
|
||||||
perms := []ec2.IPPerm{
|
req := &ec2.AuthorizeSecurityGroupIngressInput{
|
||||||
ec2.IPPerm{
|
GroupID: groupResp.GroupID,
|
||||||
Protocol: "tcp",
|
IPProtocol: aws.String("tcp"),
|
||||||
FromPort: s.SSHPort,
|
FromPort: aws.Long(int64(s.SSHPort)),
|
||||||
ToPort: s.SSHPort,
|
ToPort: aws.Long(int64(s.SSHPort)),
|
||||||
SourceIPs: []string{"0.0.0.0/0"},
|
CIDRIP: aws.String("0.0.0.0/0"),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We loop and retry this a few times because sometimes the security
|
// 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.
|
// consistent.
|
||||||
ui.Say("Authorizing SSH access on the temporary security group...")
|
ui.Say("Authorizing SSH access on the temporary security group...")
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
_, err = ec2conn.AuthorizeSecurityGroup(groupResp.SecurityGroup, perms)
|
_, err = ec2conn.AuthorizeSecurityGroupIngress(req)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -99,7 +100,7 @@ func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
for i := 0; i < 5; i++ {
|
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 {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package common
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"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 := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Inspecting the source AMI...")
|
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 {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error querying AMI: %s", err)
|
err := fmt.Errorf("Error querying AMI: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -38,11 +38,11 @@ func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
image := &imageResp.Images[0]
|
image := imageResp.Images[0]
|
||||||
|
|
||||||
// Enhanced Networking (SriovNetSupport) can only be enabled on HVM AMIs.
|
// Enhanced Networking (SriovNetSupport) can only be enabled on HVM AMIs.
|
||||||
// See http://goo.gl/icuXh5
|
// 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)
|
err := fmt.Errorf("Cannot enable enhanced networking, source AMI '%s' is not HVM", s.SourceAmi)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/common"
|
"github.com/mitchellh/packer/common"
|
||||||
|
@ -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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
auth, err := b.config.AccessConfig.Auth()
|
ec2conn := ec2.New(config)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ec2conn := ec2.New(auth, region)
|
|
||||||
|
|
||||||
// Setup the state bag and initial state for the steps
|
// Setup the state bag and initial state for the steps
|
||||||
state := new(multistep.BasicStateBag)
|
state := new(multistep.BasicStateBag)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package ebs
|
package ebs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testConfig() map[string]interface{} {
|
func testConfig() map[string]interface{} {
|
||||||
|
|
|
@ -2,7 +2,8 @@ package ebs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
@ -20,10 +21,10 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
// Create the image
|
// Create the image
|
||||||
ui.Say(fmt.Sprintf("Creating the AMI: %s", config.AMIName))
|
ui.Say(fmt.Sprintf("Creating the AMI: %s", config.AMIName))
|
||||||
createOpts := &ec2.CreateImage{
|
createOpts := &ec2.CreateImageInput{
|
||||||
InstanceId: instance.InstanceId,
|
InstanceID: instance.InstanceID,
|
||||||
Name: config.AMIName,
|
Name: &config.AMIName,
|
||||||
BlockDevices: config.BlockDevices.BuildAMIDevices(),
|
BlockDeviceMappings: config.BlockDevices.BuildAMIDevices(),
|
||||||
}
|
}
|
||||||
|
|
||||||
createResp, err := ec2conn.CreateImage(createOpts)
|
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
|
// 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 := make(map[string]string)
|
||||||
amis[ec2conn.Region.Name] = createResp.ImageId
|
amis[ec2conn.Config.Region] = *createResp.ImageID
|
||||||
state.Put("amis", amis)
|
state.Put("amis", amis)
|
||||||
|
|
||||||
// Wait for the image to become ready
|
// Wait for the image to become ready
|
||||||
stateChange := awscommon.StateChangeConf{
|
stateChange := awscommon.StateChangeConf{
|
||||||
Pending: []string{"pending"},
|
Pending: []string{"pending"},
|
||||||
Target: "available",
|
Target: "available",
|
||||||
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, createResp.ImageId),
|
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *createResp.ImageID),
|
||||||
StepState: state,
|
StepState: state,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,14 +57,14 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
imagesResp, err := ec2conn.Images([]string{createResp.ImageId}, nil)
|
imagesResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIDs: []*string{createResp.ImageID}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error searching for AMI: %s", err)
|
err := fmt.Errorf("Error searching for AMI: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
s.image = &imagesResp.Images[0]
|
s.image = imagesResp.Images[0]
|
||||||
|
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
@ -83,11 +84,9 @@ func (s *stepCreateAMI) Cleanup(state multistep.StateBag) {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Deregistering the AMI because cancelation or error...")
|
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))
|
ui.Error(fmt.Sprintf("Error deregistering AMI, may still be around: %s", err))
|
||||||
return
|
return
|
||||||
} else if resp.Return == false {
|
|
||||||
ui.Error(fmt.Sprintf("Error deregistering AMI, may still be around: %t", resp.Return))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package ebs
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"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
|
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
|
||||||
if config.AMIEnhancedNetworking {
|
if config.AMIEnhancedNetworking {
|
||||||
ui.Say("Enabling Enhanced Networking...")
|
ui.Say("Enabling Enhanced Networking...")
|
||||||
_, err := ec2conn.ModifyInstance(
|
simple := "simple"
|
||||||
instance.InstanceId,
|
_, err := ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{
|
||||||
&ec2.ModifyInstance{SriovNetSupport: true},
|
InstanceID: instance.InstanceID,
|
||||||
)
|
SRIOVNetSupport: &ec2.AttributeValue{Value: &simple},
|
||||||
|
})
|
||||||
if err != nil {
|
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)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
|
|
@ -2,7 +2,8 @@ package ebs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/goamz/ec2"
|
|
||||||
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"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
|
// Stop the instance so we can create an AMI from it
|
||||||
ui.Say("Stopping the source instance...")
|
ui.Say("Stopping the source instance...")
|
||||||
_, err := ec2conn.StopInstances(instance.InstanceId)
|
_, err := ec2conn.StopInstances(&ec2.StopInstancesInput{
|
||||||
|
InstanceIDs: []*string{instance.InstanceID},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error stopping instance: %s", err)
|
err := fmt.Errorf("Error stopping instance: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/common"
|
"github.com/mitchellh/packer/common"
|
||||||
|
@ -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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
auth, err := b.config.AccessConfig.Auth()
|
ec2conn := ec2.New(config)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ec2conn := ec2.New(auth, region)
|
|
||||||
|
|
||||||
// Setup the state bag and initial state for the steps
|
// Setup the state bag and initial state for the steps
|
||||||
state := new(multistep.BasicStateBag)
|
state := new(multistep.BasicStateBag)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package instance
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
@ -34,7 +34,7 @@ func (s *StepBundleVolume) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
var err error
|
var err error
|
||||||
config.BundleVolCommand, err = config.tpl.Process(config.BundleVolCommand, bundleCmdData{
|
config.BundleVolCommand, err = config.tpl.Process(config.BundleVolCommand, bundleCmdData{
|
||||||
AccountId: config.AccountId,
|
AccountId: config.AccountId,
|
||||||
Architecture: instance.Architecture,
|
Architecture: *instance.Architecture,
|
||||||
CertPath: x509RemoteCertPath,
|
CertPath: x509RemoteCertPath,
|
||||||
Destination: config.BundleDestination,
|
Destination: config.BundleDestination,
|
||||||
KeyPath: x509RemoteKeyPath,
|
KeyPath: x509RemoteKeyPath,
|
||||||
|
|
|
@ -3,7 +3,7 @@ package instance
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/goamz/ec2"
|
"github.com/awslabs/aws-sdk-go/service/ec2"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
awscommon "github.com/mitchellh/packer/builder/amazon/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"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 := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Registering the AMI...")
|
ui.Say("Registering the AMI...")
|
||||||
registerOpts := &ec2.RegisterImage{
|
registerOpts := &ec2.RegisterImageInput{
|
||||||
ImageLocation: manifestPath,
|
ImageLocation: &manifestPath,
|
||||||
Name: config.AMIName,
|
Name: &config.AMIName,
|
||||||
BlockDevices: config.BlockDevices.BuildAMIDevices(),
|
BlockDeviceMappings: config.BlockDevices.BuildAMIDevices(),
|
||||||
VirtType: config.AMIVirtType,
|
VirtualizationType: &config.AMIVirtType,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
|
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
|
||||||
if config.AMIEnhancedNetworking {
|
if config.AMIEnhancedNetworking {
|
||||||
registerOpts.SriovNetSupport = "simple"
|
simple := "simple"
|
||||||
|
registerOpts.SRIOVNetSupport = &simple
|
||||||
}
|
}
|
||||||
|
|
||||||
registerResp, err := ec2conn.RegisterImage(registerOpts)
|
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
|
// 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 := make(map[string]string)
|
||||||
amis[ec2conn.Region.Name] = registerResp.ImageId
|
amis[ec2conn.Config.Region] = *registerResp.ImageID
|
||||||
state.Put("amis", amis)
|
state.Put("amis", amis)
|
||||||
|
|
||||||
// Wait for the image to become ready
|
// Wait for the image to become ready
|
||||||
stateChange := awscommon.StateChangeConf{
|
stateChange := awscommon.StateChangeConf{
|
||||||
Pending: []string{"pending"},
|
Pending: []string{"pending"},
|
||||||
Target: "available",
|
Target: "available",
|
||||||
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, registerResp.ImageId),
|
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageID),
|
||||||
StepState: state,
|
StepState: state,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (s *StepUploadBundle) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
BucketName: config.S3Bucket,
|
BucketName: config.S3Bucket,
|
||||||
BundleDirectory: config.BundleDestination,
|
BundleDirectory: config.BundleDestination,
|
||||||
ManifestPath: manifestPath,
|
ManifestPath: manifestPath,
|
||||||
Region: region.Name,
|
Region: region,
|
||||||
SecretKey: config.SecretKey,
|
SecretKey: config.SecretKey,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue