Merge branch 'master' into custom-targetpath

pull/2642/head
Olivier Tremblay 11 years ago
commit 6644f57160

@ -35,8 +35,8 @@ func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction {
ui.Say(fmt.Sprintf("Attaching the root volume to %s", attachVolume))
_, err := ec2conn.AttachVolume(&ec2.AttachVolumeInput{
InstanceID: instance.InstanceID,
VolumeID: &volumeId,
InstanceId: instance.InstanceId,
VolumeId: &volumeId,
Device: &attachVolume,
})
if err != nil {
@ -58,7 +58,7 @@ func (s *StepAttachVolume) Run(state multistep.StateBag) multistep.StepAction {
Refresh: func() (interface{}, string, error) {
attempts := 0
for attempts < 30 {
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIDs: []*string{&volumeId}})
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIds: []*string{&volumeId}})
if err != nil {
return nil, "", err
}
@ -107,7 +107,7 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
ui := state.Get("ui").(packer.Ui)
ui.Say("Detaching EBS volume...")
_, err := ec2conn.DetachVolume(&ec2.DetachVolumeInput{VolumeID: &s.volumeId})
_, err := ec2conn.DetachVolume(&ec2.DetachVolumeInput{VolumeId: &s.volumeId})
if err != nil {
return fmt.Errorf("Error detaching EBS volume: %s", err)
}
@ -120,7 +120,7 @@ func (s *StepAttachVolume) CleanupFunc(state multistep.StateBag) error {
StepState: state,
Target: "detached",
Refresh: func() (interface{}, string, error) {
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIDs: []*string{&s.volumeId}})
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIds: []*string{&s.volumeId}})
if err != nil {
return nil, "", err
}

@ -45,16 +45,16 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
}
ui.Say("Creating the root volume...")
vs := *rootDevice.EBS.VolumeSize
if s.RootVolumeSize > *rootDevice.EBS.VolumeSize {
vs := *rootDevice.Ebs.VolumeSize
if s.RootVolumeSize > *rootDevice.Ebs.VolumeSize {
vs = s.RootVolumeSize
}
createVolume := &ec2.CreateVolumeInput{
AvailabilityZone: instance.Placement.AvailabilityZone,
Size: aws.Int64(vs),
SnapshotID: rootDevice.EBS.SnapshotID,
VolumeType: rootDevice.EBS.VolumeType,
IOPS: rootDevice.EBS.IOPS,
SnapshotId: rootDevice.Ebs.SnapshotId,
VolumeType: rootDevice.Ebs.VolumeType,
Iops: rootDevice.Ebs.Iops,
}
log.Printf("Create args: %s", createVolume)
@ -67,7 +67,7 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the volume ID so we remember to delete it later
s.volumeId = *createVolumeResp.VolumeID
s.volumeId = *createVolumeResp.VolumeId
log.Printf("Volume ID: %s", s.volumeId)
// Wait for the volume to become ready
@ -76,7 +76,7 @@ func (s *StepCreateVolume) Run(state multistep.StateBag) multistep.StepAction {
StepState: state,
Target: "available",
Refresh: func() (interface{}, string, error) {
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIDs: []*string{&s.volumeId}})
resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{VolumeIds: []*string{&s.volumeId}})
if err != nil {
return nil, "", err
}
@ -107,7 +107,7 @@ func (s *StepCreateVolume) Cleanup(state multistep.StateBag) {
ui := state.Get("ui").(packer.Ui)
ui.Say("Deleting the created EBS volume...")
_, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeID: &s.volumeId})
_, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeId: &s.volumeId})
if err != nil {
ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err))
}

@ -34,7 +34,7 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
log.Printf("Instance ID: %s", instanceId)
// Query the entire instance metadata
instancesResp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{InstanceIDs: []*string{&instanceId}})
instancesResp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesInput{InstanceIds: []*string{&instanceId}})
if err != nil {
err := fmt.Errorf("Error getting instance data: %s", err)
state.Put("error", err)

@ -27,21 +27,21 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
for i, device := range image.BlockDeviceMappings {
newDevice := device
if *newDevice.DeviceName == *image.RootDeviceName {
if newDevice.EBS != nil {
newDevice.EBS.SnapshotID = aws.String(snapshotId)
if newDevice.Ebs != nil {
newDevice.Ebs.SnapshotId = aws.String(snapshotId)
} else {
newDevice.EBS = &ec2.EBSBlockDevice{SnapshotID: aws.String(snapshotId)}
newDevice.Ebs = &ec2.EbsBlockDevice{SnapshotId: aws.String(snapshotId)}
}
if s.RootVolumeSize > *newDevice.EBS.VolumeSize {
newDevice.EBS.VolumeSize = aws.Int64(s.RootVolumeSize)
if s.RootVolumeSize > *newDevice.Ebs.VolumeSize {
newDevice.Ebs.VolumeSize = aws.Int64(s.RootVolumeSize)
}
}
// assume working from a snapshot, so we unset the Encrypted field if set,
// otherwise AWS API will return InvalidParameter
if newDevice.EBS != nil && newDevice.EBS.Encrypted != nil {
newDevice.EBS.Encrypted = nil
if newDevice.Ebs != nil && newDevice.Ebs.Encrypted != nil {
newDevice.Ebs.Encrypted = nil
}
blockDevices[i] = newDevice
@ -51,7 +51,7 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
if config.AMIEnhancedNetworking {
registerOpts.SRIOVNetSupport = aws.String("simple")
registerOpts.SriovNetSupport = aws.String("simple")
}
registerResp, err := ec2conn.RegisterImage(registerOpts)
@ -62,16 +62,16 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the AMI ID in the state
ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageID))
ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageId))
amis := make(map[string]string)
amis[*ec2conn.Config.Region] = *registerResp.ImageID
amis[*ec2conn.Config.Region] = *registerResp.ImageId
state.Put("amis", amis)
// Wait for the image to become ready
stateChange := awscommon.StateChangeConf{
Pending: []string{"pending"},
Target: "available",
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageID),
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageId),
StepState: state,
}
@ -102,8 +102,8 @@ func buildRegisterOpts(config *Config, image *ec2.Image, blockDevices []*ec2.Blo
}
if config.AMIVirtType != "hvm" {
registerOpts.KernelID = image.KernelID
registerOpts.RAMDiskID = image.RAMDiskID
registerOpts.KernelId = image.KernelId
registerOpts.RamdiskId = image.RamdiskId
}
return registerOpts

@ -9,10 +9,10 @@ import (
func testImage() ec2.Image {
return ec2.Image{
ImageID: aws.String("ami-abcd1234"),
ImageId: aws.String("ami-abcd1234"),
Name: aws.String("ami_test_name"),
Architecture: aws.String("x86_64"),
KernelID: aws.String("aki-abcd1234"),
KernelId: aws.String("aki-abcd1234"),
}
}
@ -38,9 +38,9 @@ func TestStepRegisterAmi_buildRegisterOpts_pv(t *testing.T) {
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, *opts.Name)
}
expected = *image.KernelID
if *opts.KernelID != expected {
t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, *opts.KernelID)
expected = *image.KernelId
if *opts.KernelId != expected {
t.Fatalf("Unexpected KernelId value: expected %s got %s\n", expected, *opts.KernelId)
}
}
@ -67,7 +67,7 @@ func TestStepRegisterAmi_buildRegisterOpts_hvm(t *testing.T) {
t.Fatalf("Unexpected Name value: expected %s got %s\n", expected, *opts.Name)
}
if opts.KernelID != nil {
t.Fatalf("Unexpected KernelId value: expected nil got %s\n", *opts.KernelID)
if opts.KernelId != nil {
t.Fatalf("Unexpected KernelId value: expected nil got %s\n", *opts.KernelId)
}
}

@ -28,7 +28,7 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
description := fmt.Sprintf("Packer: %s", time.Now().String())
createSnapResp, err := ec2conn.CreateSnapshot(&ec2.CreateSnapshotInput{
VolumeID: &volumeId,
VolumeId: &volumeId,
Description: &description,
})
if err != nil {
@ -39,7 +39,7 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the snapshot ID so we can delete it later
s.snapshotId = *createSnapResp.SnapshotID
s.snapshotId = *createSnapResp.SnapshotId
ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId))
// Wait for the snapshot to be ready
@ -48,7 +48,7 @@ func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
StepState: state,
Target: "completed",
Refresh: func() (interface{}, string, error) {
resp, err := ec2conn.DescribeSnapshots(&ec2.DescribeSnapshotsInput{SnapshotIDs: []*string{&s.snapshotId}})
resp, err := ec2conn.DescribeSnapshots(&ec2.DescribeSnapshotsInput{SnapshotIds: []*string{&s.snapshotId}})
if err != nil {
return nil, "", err
}
@ -86,7 +86,7 @@ func (s *StepSnapshot) Cleanup(state multistep.StateBag) {
ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui)
ui.Say("Removing snapshot since we cancelled or halted...")
_, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{SnapshotID: &s.snapshotId})
_, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{SnapshotId: &s.snapshotId})
if err != nil {
ui.Error(fmt.Sprintf("Error: %s", err))
}

@ -75,7 +75,7 @@ func (a *Artifact) Destroy() error {
regionConn := ec2.New(regionConfig)
input := &ec2.DeregisterImageInput{
ImageID: &imageId,
ImageId: &imageId,
}
if _, err := regionConn.DeregisterImage(input); err != nil {
errors = append(errors, err)

@ -30,7 +30,7 @@ func buildBlockDevices(b []BlockDevice) []*ec2.BlockDeviceMapping {
var blockDevices []*ec2.BlockDeviceMapping
for _, blockDevice := range b {
ebsBlockDevice := &ec2.EBSBlockDevice{
ebsBlockDevice := &ec2.EbsBlockDevice{
VolumeType: aws.String(blockDevice.VolumeType),
VolumeSize: aws.Int64(blockDevice.VolumeSize),
DeleteOnTermination: aws.Bool(blockDevice.DeleteOnTermination),
@ -38,12 +38,12 @@ func buildBlockDevices(b []BlockDevice) []*ec2.BlockDeviceMapping {
// IOPS is only valid for SSD Volumes
if blockDevice.VolumeType != "" && blockDevice.VolumeType != "standard" && blockDevice.VolumeType != "gp2" {
ebsBlockDevice.IOPS = aws.Int64(blockDevice.IOPS)
ebsBlockDevice.Iops = aws.Int64(blockDevice.IOPS)
}
// You cannot specify Encrypted if you specify a Snapshot ID
if blockDevice.SnapshotId != "" {
ebsBlockDevice.SnapshotID = aws.String(blockDevice.SnapshotId)
ebsBlockDevice.SnapshotId = aws.String(blockDevice.SnapshotId)
} else if blockDevice.Encrypted {
ebsBlockDevice.Encrypted = aws.Bool(blockDevice.Encrypted)
}
@ -54,7 +54,7 @@ func buildBlockDevices(b []BlockDevice) []*ec2.BlockDeviceMapping {
}
if !strings.HasPrefix(blockDevice.VirtualName, "ephemeral") {
mapping.EBS = ebsBlockDevice
mapping.Ebs = ebsBlockDevice
}
if blockDevice.NoDevice {

@ -25,8 +25,8 @@ func TestBlockDevice(t *testing.T) {
Result: &ec2.BlockDeviceMapping{
DeviceName: aws.String("/dev/sdb"),
VirtualName: aws.String(""),
EBS: &ec2.EBSBlockDevice{
SnapshotID: aws.String("snap-1234"),
Ebs: &ec2.EbsBlockDevice{
SnapshotId: aws.String("snap-1234"),
VolumeType: aws.String("standard"),
VolumeSize: aws.Int64(8),
DeleteOnTermination: aws.Bool(true),
@ -42,7 +42,7 @@ func TestBlockDevice(t *testing.T) {
Result: &ec2.BlockDeviceMapping{
DeviceName: aws.String("/dev/sdb"),
VirtualName: aws.String(""),
EBS: &ec2.EBSBlockDevice{
Ebs: &ec2.EbsBlockDevice{
VolumeType: aws.String(""),
VolumeSize: aws.Int64(8),
DeleteOnTermination: aws.Bool(false),
@ -61,11 +61,11 @@ func TestBlockDevice(t *testing.T) {
Result: &ec2.BlockDeviceMapping{
DeviceName: aws.String("/dev/sdb"),
VirtualName: aws.String(""),
EBS: &ec2.EBSBlockDevice{
Ebs: &ec2.EbsBlockDevice{
VolumeType: aws.String("io1"),
VolumeSize: aws.Int64(8),
DeleteOnTermination: aws.Bool(true),
IOPS: aws.Int64(1000),
Iops: aws.Int64(1000),
},
},
},

@ -17,14 +17,14 @@ func SSHHost(e *ec2.EC2, private bool) func(multistep.StateBag) (string, error)
for j := 0; j < 2; j++ {
var host string
i := state.Get("instance").(*ec2.Instance)
if i.VPCID != nil && *i.VPCID != "" {
if i.PublicIPAddress != nil && *i.PublicIPAddress != "" && !private {
host = *i.PublicIPAddress
if i.VpcId != nil && *i.VpcId != "" {
if i.PublicIpAddress != nil && *i.PublicIpAddress != "" && !private {
host = *i.PublicIpAddress
} else {
host = *i.PrivateIPAddress
host = *i.PrivateIpAddress
}
} else if i.PublicDNSName != nil && *i.PublicDNSName != "" {
host = *i.PublicDNSName
} else if i.PublicDnsName != nil && *i.PublicDnsName != "" {
host = *i.PublicDnsName
}
if host != "" {
@ -32,14 +32,14 @@ func SSHHost(e *ec2.EC2, private bool) func(multistep.StateBag) (string, error)
}
r, err := e.DescribeInstances(&ec2.DescribeInstancesInput{
InstanceIDs: []*string{i.InstanceID},
InstanceIds: []*string{i.InstanceId},
})
if err != nil {
return "", err
}
if len(r.Reservations) == 0 || len(r.Reservations[0].Instances) == 0 {
return "", fmt.Errorf("instance not found: %s", *i.InstanceID)
return "", fmt.Errorf("instance not found: %s", *i.InstanceId)
}
state.Put("instance", &r.Reservations[0].Instances[0])

@ -39,7 +39,7 @@ type StateChangeConf struct {
func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.DescribeImages(&ec2.DescribeImagesInput{
ImageIDs: []*string{&imageId},
ImageIds: []*string{&imageId},
})
if err != nil {
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidAMIID.NotFound" {
@ -70,7 +70,7 @@ func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc {
func InstanceStateRefreshFunc(conn *ec2.EC2, instanceId string) StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.DescribeInstances(&ec2.DescribeInstancesInput{
InstanceIDs: []*string{&instanceId},
InstanceIds: []*string{&instanceId},
})
if err != nil {
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidInstanceID.NotFound" {
@ -101,7 +101,7 @@ func InstanceStateRefreshFunc(conn *ec2.EC2, instanceId string) StateRefreshFunc
func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{
SpotInstanceRequestIDs: []*string{&spotRequestId},
SpotInstanceRequestIds: []*string{&spotRequestId},
})
if err != nil {

@ -90,7 +90,7 @@ func amiRegionCopy(state multistep.StateBag, config *AccessConfig, name string,
regionconn := ec2.New(awsConfig)
resp, err := regionconn.CopyImage(&ec2.CopyImageInput{
SourceRegion: &source,
SourceImageID: &imageId,
SourceImageId: &imageId,
Name: &name,
})
@ -102,14 +102,14 @@ func amiRegionCopy(state multistep.StateBag, config *AccessConfig, name string,
stateChange := StateChangeConf{
Pending: []string{"pending"},
Target: "available",
Refresh: AMIStateRefreshFunc(regionconn, *resp.ImageID),
Refresh: AMIStateRefreshFunc(regionconn, *resp.ImageId),
StepState: state,
}
if _, err := WaitForState(&stateChange); err != nil {
return "", fmt.Errorf("Error waiting for AMI (%s) in region (%s): %s",
*resp.ImageID, target, err)
*resp.ImageId, target, err)
}
return *resp.ImageID, nil
return *resp.ImageId, nil
}

@ -41,7 +41,7 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction {
// Retrieve image list for given AMI
imageResp, err := regionconn.DescribeImages(&ec2.DescribeImagesInput{
ImageIDs: resourceIds,
ImageIds: resourceIds,
})
if err != nil {
@ -62,9 +62,9 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction {
// Add only those with a Snapshot ID, i.e. not Ephemeral
for _, device := range image.BlockDeviceMappings {
if device.EBS != nil && device.EBS.SnapshotID != nil {
ui.Say(fmt.Sprintf("Tagging snapshot: %s", *device.EBS.SnapshotID))
resourceIds = append(resourceIds, device.EBS.SnapshotID)
if device.Ebs != nil && device.Ebs.SnapshotId != nil {
ui.Say(fmt.Sprintf("Tagging snapshot: %s", *device.Ebs.SnapshotId))
resourceIds = append(resourceIds, device.Ebs.SnapshotId)
}
}

@ -36,7 +36,7 @@ func (s *StepDeregisterAMI) Run(state multistep.StateBag) multistep.StepAction {
// deregister image(s) by that name
for _, i := range resp.Images {
_, err := ec2conn.DeregisterImage(&ec2.DeregisterImageInput{
ImageID: i.ImageID,
ImageId: i.ImageId,
})
if err != nil {
@ -45,7 +45,7 @@ func (s *StepDeregisterAMI) Run(state multistep.StateBag) multistep.StepAction {
ui.Error(err.Error())
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("Deregistered AMI %s, id: %s", s.AMIName, *i.ImageID))
ui.Say(fmt.Sprintf("Deregistered AMI %s, id: %s", s.AMIName, *i.ImageId))
}
}

@ -111,7 +111,7 @@ func (s *StepGetPassword) waitForPassword(state multistep.StateBag, cancel <-cha
}
resp, err := ec2conn.GetPasswordData(&ec2.GetPasswordDataInput{
InstanceID: instance.InstanceID,
InstanceId: instance.InstanceId,
})
if err != nil {
err := fmt.Errorf("Error retrieving auto-generated instance password: %s", err)

@ -66,10 +66,10 @@ func (s *StepModifyAMIAttributes) Run(state multistep.StateBag) multistep.StepAc
adds := make([]*ec2.LaunchPermission, len(s.Users))
for i, u := range s.Users {
users[i] = aws.String(u)
adds[i] = &ec2.LaunchPermission{UserID: aws.String(u)}
adds[i] = &ec2.LaunchPermission{UserId: aws.String(u)}
}
options["users"] = &ec2.ModifyImageAttributeInput{
UserIDs: users,
UserIds: users,
LaunchPermission: &ec2.LaunchPermissionModifications{
Add: adds,
},
@ -94,7 +94,7 @@ func (s *StepModifyAMIAttributes) Run(state multistep.StateBag) multistep.StepAc
})
for name, input := range options {
ui.Message(fmt.Sprintf("Modifying: %s", name))
input.ImageID = &ami
input.ImageId = &ami
_, err := regionconn.ModifyImageAttribute(input)
if err != nil {
err := fmt.Errorf("Error modify AMI attributes: %s", err)

@ -41,7 +41,7 @@ func (s *StepPreValidate) Run(state multistep.StateBag) multistep.StepAction {
}
if len(resp.Images) > 0 {
err := fmt.Errorf("Error: name conflicts with an existing AMI: %s", *resp.Images[0].ImageID)
err := fmt.Errorf("Error: name conflicts with an existing AMI: %s", *resp.Images[0].ImageId)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt

@ -66,7 +66,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
ui.Say("Launching a source AWS instance...")
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
ImageIDs: []*string{&s.SourceAMI},
ImageIds: []*string{&s.SourceAMI},
})
if err != nil {
state.Put("error", fmt.Errorf("There was a problem with the source AMI: %s", err))
@ -138,12 +138,12 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
if spotPrice == "" {
runOpts := &ec2.RunInstancesInput{
KeyName: &keyName,
ImageID: &s.SourceAMI,
ImageId: &s.SourceAMI,
InstanceType: &s.InstanceType,
UserData: &userData,
MaxCount: aws.Int64(1),
MinCount: aws.Int64(1),
IAMInstanceProfile: &ec2.IAMInstanceProfileSpecification{Name: &s.IamInstanceProfile},
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile},
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
Placement: &ec2.Placement{AvailabilityZone: &s.AvailabilityZone},
}
@ -152,15 +152,15 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
runOpts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{
&ec2.InstanceNetworkInterfaceSpecification{
DeviceIndex: aws.Int64(0),
AssociatePublicIPAddress: &s.AssociatePublicIpAddress,
SubnetID: &s.SubnetId,
AssociatePublicIpAddress: &s.AssociatePublicIpAddress,
SubnetId: &s.SubnetId,
Groups: securityGroupIds,
DeleteOnTermination: aws.Bool(true),
},
}
} else {
runOpts.SubnetID = &s.SubnetId
runOpts.SecurityGroupIDs = securityGroupIds
runOpts.SubnetId = &s.SubnetId
runOpts.SecurityGroupIds = securityGroupIds
}
runResp, err := ec2conn.RunInstances(runOpts)
@ -170,7 +170,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
ui.Error(err.Error())
return multistep.ActionHalt
}
instanceId = *runResp.Instances[0].InstanceID
instanceId = *runResp.Instances[0].InstanceId
} else {
ui.Message(fmt.Sprintf(
"Requesting spot instance '%s' for: %s",
@ -179,15 +179,15 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
SpotPrice: &spotPrice,
LaunchSpecification: &ec2.RequestSpotLaunchSpecification{
KeyName: &keyName,
ImageID: &s.SourceAMI,
ImageId: &s.SourceAMI,
InstanceType: &s.InstanceType,
UserData: &userData,
IAMInstanceProfile: &ec2.IAMInstanceProfileSpecification{Name: &s.IamInstanceProfile},
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile},
NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{
&ec2.InstanceNetworkInterfaceSpecification{
DeviceIndex: aws.Int64(0),
AssociatePublicIPAddress: &s.AssociatePublicIpAddress,
SubnetID: &s.SubnetId,
AssociatePublicIpAddress: &s.AssociatePublicIpAddress,
SubnetId: &s.SubnetId,
Groups: securityGroupIds,
DeleteOnTermination: aws.Bool(true),
},
@ -207,7 +207,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
s.spotRequest = runSpotResp.SpotInstanceRequests[0]
spotRequestId := s.spotRequest.SpotInstanceRequestID
spotRequestId := s.spotRequest.SpotInstanceRequestId
ui.Message(fmt.Sprintf("Waiting for spot request (%s) to become active...", *spotRequestId))
stateChange := StateChangeConf{
Pending: []string{"open"},
@ -224,7 +224,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
}
spotResp, err := ec2conn.DescribeSpotInstanceRequests(&ec2.DescribeSpotInstanceRequestsInput{
SpotInstanceRequestIDs: []*string{spotRequestId},
SpotInstanceRequestIds: []*string{spotRequestId},
})
if err != nil {
err := fmt.Errorf("Error finding spot request (%s): %s", *spotRequestId, err)
@ -232,7 +232,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
ui.Error(err.Error())
return multistep.ActionHalt
}
instanceId = *spotResp.SpotInstanceRequests[0].InstanceID
instanceId = *spotResp.SpotInstanceRequests[0].InstanceId
}
// Set the instance ID so that the cleanup works properly
@ -264,7 +264,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
_, err = ec2conn.CreateTags(&ec2.CreateTagsInput{
Tags: ec2Tags,
Resources: []*string{instance.InstanceID},
Resources: []*string{instance.InstanceId},
})
if err != nil {
ui.Message(
@ -272,16 +272,16 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
}
if s.Debug {
if instance.PublicDNSName != nil && *instance.PublicDNSName != "" {
ui.Message(fmt.Sprintf("Public DNS: %s", *instance.PublicDNSName))
if instance.PublicDnsName != nil && *instance.PublicDnsName != "" {
ui.Message(fmt.Sprintf("Public DNS: %s", *instance.PublicDnsName))
}
if instance.PublicIPAddress != nil && *instance.PublicIPAddress != "" {
ui.Message(fmt.Sprintf("Public IP: %s", *instance.PublicIPAddress))
if instance.PublicIpAddress != nil && *instance.PublicIpAddress != "" {
ui.Message(fmt.Sprintf("Public IP: %s", *instance.PublicIpAddress))
}
if instance.PrivateIPAddress != nil && *instance.PrivateIPAddress != "" {
ui.Message(fmt.Sprintf("Private IP: %s", *instance.PrivateIPAddress))
if instance.PrivateIpAddress != nil && *instance.PrivateIpAddress != "" {
ui.Message(fmt.Sprintf("Private IP: %s", *instance.PrivateIpAddress))
}
}
@ -299,7 +299,7 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
if s.spotRequest != nil {
ui.Say("Cancelling the spot request...")
input := &ec2.CancelSpotInstanceRequestsInput{
SpotInstanceRequestIDs: []*string{s.spotRequest.SpotInstanceRequestID},
SpotInstanceRequestIds: []*string{s.spotRequest.SpotInstanceRequestId},
}
if _, err := ec2conn.CancelSpotInstanceRequests(input); err != nil {
ui.Error(fmt.Sprintf("Error cancelling the spot request, may still be around: %s", err))
@ -307,7 +307,7 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
}
stateChange := StateChangeConf{
Pending: []string{"active", "open"},
Refresh: SpotRequestStateRefreshFunc(ec2conn, *s.spotRequest.SpotInstanceRequestID),
Refresh: SpotRequestStateRefreshFunc(ec2conn, *s.spotRequest.SpotInstanceRequestId),
Target: "cancelled",
}
@ -318,7 +318,7 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
// Terminate the source instance if it exists
if s.instanceId != "" {
ui.Say("Terminating the source AWS instance...")
if _, err := ec2conn.TerminateInstances(&ec2.TerminateInstancesInput{InstanceIDs: []*string{&s.instanceId}}); err != nil {
if _, err := ec2conn.TerminateInstances(&ec2.TerminateInstancesInput{InstanceIds: []*string{&s.instanceId}}); err != nil {
ui.Error(fmt.Sprintf("Error terminating instance, may still be around: %s", err))
return
}

@ -43,7 +43,7 @@ func (s *StepSecurityGroup) Run(state multistep.StateBag) multistep.StepAction {
group := &ec2.CreateSecurityGroupInput{
GroupName: &groupName,
Description: aws.String("Temporary group for Packer"),
VPCID: &s.VpcId,
VpcId: &s.VpcId,
}
groupResp, err := ec2conn.CreateSecurityGroup(group)
if err != nil {
@ -53,15 +53,15 @@ func (s *StepSecurityGroup) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the group ID so we can delete it later
s.createdGroupId = *groupResp.GroupID
s.createdGroupId = *groupResp.GroupId
// Authorize the SSH access for the security group
req := &ec2.AuthorizeSecurityGroupIngressInput{
GroupID: groupResp.GroupID,
IPProtocol: aws.String("tcp"),
GroupId: groupResp.GroupId,
IpProtocol: aws.String("tcp"),
FromPort: aws.Int64(int64(port)),
ToPort: aws.Int64(int64(port)),
CIDRIP: aws.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
@ -105,7 +105,7 @@ func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) {
var err error
for i := 0; i < 5; i++ {
_, err = ec2conn.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{GroupID: &s.createdGroupId})
_, err = ec2conn.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{GroupId: &s.createdGroupId})
if err == nil {
break
}

@ -23,7 +23,7 @@ func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
ui.Say("Inspecting the source AMI...")
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIDs: []*string{&s.SourceAmi}})
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{&s.SourceAmi}})
if err != nil {
err := fmt.Errorf("Error querying AMI: %s", err)
state.Put("error", err)

@ -71,7 +71,7 @@ func checkAMISharing(count int, uid, group string) builderT.TestCheckFunc {
ec2conn, _ := testEC2Conn()
imageResp, err := ec2conn.DescribeImageAttribute(&ec2.DescribeImageAttributeInput{
Attribute: aws.String("launchPermission"),
ImageID: aws.String(artifact.Amis["us-east-1"]),
ImageId: aws.String(artifact.Amis["us-east-1"]),
})
if err != nil {
@ -86,7 +86,7 @@ func checkAMISharing(count int, uid, group string) builderT.TestCheckFunc {
userFound := false
for _, lp := range imageResp.LaunchPermissions {
if lp.UserID != nil && uid == *lp.UserID {
if lp.UserId != nil && uid == *lp.UserId {
userFound = true
}
}

@ -62,9 +62,9 @@ func (s *stepCleanupVolumes) Cleanup(state multistep.StateBag) {
var vl []*string
volList := make(map[string]string)
for _, bdm := range instance.BlockDeviceMappings {
if bdm.EBS != nil {
vl = append(vl, bdm.EBS.VolumeID)
volList[*bdm.EBS.VolumeID] = *bdm.DeviceName
if bdm.Ebs != nil {
vl = append(vl, bdm.Ebs.VolumeId)
volList[*bdm.Ebs.VolumeId] = *bdm.DeviceName
}
}
@ -88,7 +88,7 @@ func (s *stepCleanupVolumes) Cleanup(state multistep.StateBag) {
// available, remove them from the list of volumes
for _, v := range resp.Volumes {
if v.State != nil && *v.State != "available" {
delete(volList, *v.VolumeID)
delete(volList, *v.VolumeId)
}
}
@ -109,7 +109,7 @@ func (s *stepCleanupVolumes) Cleanup(state multistep.StateBag) {
// Destroy remaining volumes
for k, _ := range volList {
ui.Say(fmt.Sprintf("Destroying volume (%s)...", k))
_, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeID: aws.String(k)})
_, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeId: aws.String(k)})
if err != nil {
ui.Say(fmt.Sprintf("Error deleting volume: %s", k))
}

@ -22,7 +22,7 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
// Create the image
ui.Say(fmt.Sprintf("Creating the AMI: %s", config.AMIName))
createOpts := &ec2.CreateImageInput{
InstanceID: instance.InstanceID,
InstanceId: instance.InstanceId,
Name: &config.AMIName,
BlockDeviceMappings: config.BlockDevices.BuildAMIDevices(),
}
@ -36,16 +36,16 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the AMI ID in the state
ui.Message(fmt.Sprintf("AMI: %s", *createResp.ImageID))
ui.Message(fmt.Sprintf("AMI: %s", *createResp.ImageId))
amis := make(map[string]string)
amis[*ec2conn.Config.Region] = *createResp.ImageID
amis[*ec2conn.Config.Region] = *createResp.ImageId
state.Put("amis", amis)
// Wait for the image to become ready
stateChange := awscommon.StateChangeConf{
Pending: []string{"pending"},
Target: "available",
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *createResp.ImageID),
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *createResp.ImageId),
StepState: state,
}
@ -57,7 +57,7 @@ func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
imagesResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIDs: []*string{createResp.ImageID}})
imagesResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{createResp.ImageId}})
if err != nil {
err := fmt.Errorf("Error searching for AMI: %s", err)
state.Put("error", err)
@ -84,7 +84,7 @@ func (s *stepCreateAMI) Cleanup(state multistep.StateBag) {
ui := state.Get("ui").(packer.Ui)
ui.Say("Deregistering the AMI because cancelation or error...")
deregisterOpts := &ec2.DeregisterImageInput{ImageID: s.image.ImageID}
deregisterOpts := &ec2.DeregisterImageInput{ImageId: s.image.ImageId}
if _, err := ec2conn.DeregisterImage(deregisterOpts); err != nil {
ui.Error(fmt.Sprintf("Error deregistering AMI, may still be around: %s", err))
return

@ -21,11 +21,11 @@ func (s *stepModifyInstance) Run(state multistep.StateBag) multistep.StepAction
ui.Say("Enabling Enhanced Networking...")
simple := "simple"
_, err := ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{
InstanceID: instance.InstanceID,
SRIOVNetSupport: &ec2.AttributeValue{Value: &simple},
InstanceId: instance.InstanceId,
SriovNetSupport: &ec2.AttributeValue{Value: &simple},
})
if err != nil {
err := fmt.Errorf("Error enabling Enhanced Networking on %s: %s", *instance.InstanceID, err)
err := fmt.Errorf("Error enabling Enhanced Networking on %s: %s", *instance.InstanceId, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt

@ -26,7 +26,7 @@ func (s *stepStopInstance) Run(state multistep.StateBag) multistep.StepAction {
// Stop the instance so we can create an AMI from it
ui.Say("Stopping the source instance...")
_, err := ec2conn.StopInstances(&ec2.StopInstancesInput{
InstanceIDs: []*string{instance.InstanceID},
InstanceIds: []*string{instance.InstanceId},
})
if err != nil {
err := fmt.Errorf("Error stopping instance: %s", err)
@ -40,7 +40,7 @@ func (s *stepStopInstance) Run(state multistep.StateBag) multistep.StepAction {
stateChange := awscommon.StateChangeConf{
Pending: []string{"running", "stopping"},
Target: "stopped",
Refresh: awscommon.InstanceStateRefreshFunc(ec2conn, *instance.InstanceID),
Refresh: awscommon.InstanceStateRefreshFunc(ec2conn, *instance.InstanceId),
StepState: state,
}
_, err = awscommon.WaitForState(&stateChange)

@ -40,7 +40,7 @@ func checkTags() builderT.TestCheckFunc {
// describe the image, get block devices with a snapshot
ec2conn, _ := testEC2Conn()
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
ImageIDs: []*string{aws.String(artifact.Amis["us-east-1"])},
ImageIds: []*string{aws.String(artifact.Amis["us-east-1"])},
})
if err != nil {
@ -56,14 +56,14 @@ func checkTags() builderT.TestCheckFunc {
// Check only those with a Snapshot ID, i.e. not Ephemeral
var snapshots []*string
for _, device := range image.BlockDeviceMappings {
if device.EBS != nil && device.EBS.SnapshotID != nil {
snapshots = append(snapshots, device.EBS.SnapshotID)
if device.Ebs != nil && device.Ebs.SnapshotId != nil {
snapshots = append(snapshots, device.Ebs.SnapshotId)
}
}
// grab matching snapshot info
resp, err := ec2conn.DescribeSnapshots(&ec2.DescribeSnapshotsInput{
SnapshotIDs: snapshots,
SnapshotIds: snapshots,
})
if err != nil {

@ -31,7 +31,7 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
if config.AMIEnhancedNetworking {
registerOpts.SRIOVNetSupport = aws.String("simple")
registerOpts.SriovNetSupport = aws.String("simple")
}
registerResp, err := ec2conn.RegisterImage(registerOpts)
@ -42,16 +42,16 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
}
// Set the AMI ID in the state
ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageID))
ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageId))
amis := make(map[string]string)
amis[*ec2conn.Config.Region] = *registerResp.ImageID
amis[*ec2conn.Config.Region] = *registerResp.ImageId
state.Put("amis", amis)
// Wait for the image to become ready
stateChange := awscommon.StateChangeConf{
Pending: []string{"pending"},
Target: "available",
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageID),
Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageId),
StepState: state,
}

@ -9,8 +9,10 @@ import (
"github.com/mitchellh/packer/packer"
)
const BuilderId = "packer.docker"
const BuilderIdImport = "packer.post-processor.docker-import"
const (
BuilderId = "packer.docker"
BuilderIdImport = "packer.post-processor.docker-import"
)
type Builder struct {
config *Config
@ -54,10 +56,16 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&common.StepProvision{},
}
if b.config.Commit {
if b.config.Discard {
log.Print("[DEBUG] Container will be discarded")
} else if b.config.Commit {
log.Print("[DEBUG] Container will be committed")
steps = append(steps, new(StepCommit))
} else {
} else if b.config.ExportPath != "" {
log.Printf("[DEBUG] Container will be exported to %s", b.config.ExportPath)
steps = append(steps, new(StepExport))
} else {
return nil, errArtifactNotUsed
}
// Setup the state bag and initial state for the steps

@ -12,23 +12,33 @@ import (
"github.com/mitchellh/packer/template/interpolate"
)
var (
errArtifactNotUsed = fmt.Errorf("No instructions given for handling the artifact; expected commit, discard, or export_path")
errArtifactUseConflict = fmt.Errorf("Cannot specify more than one of commit, discard, and export_path")
errExportPathNotFile = fmt.Errorf("export_path must be a file, not a directory")
errImageNotSpecified = fmt.Errorf("Image must be specified")
)
type Config struct {
common.PackerConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
Commit bool
Discard bool
ExportPath string `mapstructure:"export_path"`
Image string
Pty bool
Pull bool
RunCommand []string `mapstructure:"run_command"`
Volumes map[string]string
// This is used to login to dockerhub to pull a private base container. For
// pushing to dockerhub, see the docker post-processors
Login bool
LoginEmail string `mapstructure:"login_email"`
LoginUsername string `mapstructure:"login_username"`
LoginPassword string `mapstructure:"login_password"`
LoginServer string `mapstructure:"login_server"`
Pty bool
LoginUsername string `mapstructure:"login_username"`
ctx interpolate.Context
}
@ -53,11 +63,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
// Defaults
if len(c.RunCommand) == 0 {
c.RunCommand = []string{
"-d", "-i", "-t",
"{{.Image}}",
"/bin/bash",
}
c.RunCommand = []string{"-d", "-i", "-t", "{{.Image}}", "/bin/bash"}
}
// Default Pull if it wasn't set
@ -83,19 +89,20 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, es...)
}
if c.Image == "" {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("image must be specified"))
errs = packer.MultiErrorAppend(errs, errImageNotSpecified)
}
if (c.ExportPath != "" && c.Commit) || (c.ExportPath != "" && c.Discard) || (c.Commit && c.Discard) {
errs = packer.MultiErrorAppend(errs, errArtifactUseConflict)
}
if c.ExportPath != "" && c.Commit {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("both commit and export_path cannot be set"))
if c.ExportPath == "" && !c.Commit && !c.Discard {
errs = packer.MultiErrorAppend(errs, errArtifactNotUsed)
}
if c.ExportPath != "" {
if fi, err := os.Stat(c.ExportPath); err == nil && fi.IsDir() {
errs = packer.MultiErrorAppend(errs, fmt.Errorf(
"export_path must be a file, not a directory"))
errs = packer.MultiErrorAppend(errs, errExportPathNotFile)
}
}

@ -2,9 +2,10 @@ package docker
import (
"fmt"
"os"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"os"
)
// StepExport exports the container to a flat tar file.
@ -17,6 +18,14 @@ func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
containerId := state.Get("container_id").(string)
ui := state.Get("ui").(packer.Ui)
// We should catch this in validation, but guard anyway
if config.ExportPath == "" {
err := fmt.Errorf("No output file specified, we can't export anything")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
// Open the file that we're going to write to
f, err := os.Create(config.ExportPath)
if err != nil {

@ -202,14 +202,15 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
b.config.VNCPortMax = 6000
}
if b.config.VMName == "" {
b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName)
}
if b.config.Format == "" {
b.config.Format = "qcow2"
}
if b.config.VMName == "" {
b.config.VMName = fmt.Sprintf("packer-%s.%s",
b.config.PackerBuildName, b.config.Format)
}
if b.config.FloppyFiles == nil {
b.config.FloppyFiles = make([]string, 0)
}

@ -101,7 +101,7 @@ func (d *DownloadClient) Cancel() {
func (d *DownloadClient) Get() (string, error) {
// If we already have the file and it matches, then just return the target path.
if verify, _ := d.VerifyChecksum(d.config.TargetPath); verify {
log.Println("Initial checksum matched, no download needed.")
log.Println("[DEBUG] Initial checksum matched, no download needed.")
return d.config.TargetPath, nil
}
@ -115,13 +115,19 @@ func (d *DownloadClient) Get() (string, error) {
// Files when we don't copy the file are special cased.
var f *os.File
var finalPath string
sourcePath := ""
if url.Scheme == "file" && !d.config.CopyFile {
// This is a special case where we use a source file that already exists
// locally and we don't make a copy. Normally we would copy or download.
finalPath = url.Path
log.Printf("[DEBUG] Using local file: %s", finalPath)
// Remove forward slash on absolute Windows file URLs before processing
if runtime.GOOS == "windows" && len(finalPath) > 0 && finalPath[0] == '/' {
finalPath = finalPath[1:len(finalPath)]
}
// Keep track of the source so we can make sure not to delete this later
sourcePath = finalPath
} else {
finalPath = d.config.TargetPath
@ -137,7 +143,7 @@ func (d *DownloadClient) Get() (string, error) {
return "", err
}
log.Printf("Downloading: %s", url.String())
log.Printf("[DEBUG] Downloading: %s", url.String())
err = d.downloader.Download(f, url)
f.Close()
if err != nil {
@ -149,8 +155,10 @@ func (d *DownloadClient) Get() (string, error) {
var verify bool
verify, err = d.VerifyChecksum(finalPath)
if err == nil && !verify {
// Delete the file
os.Remove(finalPath)
// Only delete the file if we made a copy or downloaded it
if sourcePath != finalPath {
os.Remove(finalPath)
}
err = fmt.Errorf(
"checksums didn't match expected: %s",

@ -3,6 +3,7 @@ package common
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
@ -338,3 +339,40 @@ func TestHashForType(t *testing.T) {
t.Fatalf("fake hash is not nil")
}
}
// TestDownloadFileUrl tests a special case where we use a local file for
// iso_url. In this case we can still verify the checksum but we should not
// delete the file if the checksum fails. Instead we'll just error and let the
// user fix the checksum.
func TestDownloadFileUrl(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("Unable to detect working directory: %s", err)
}
// source_path is a file path and source is a network path
sourcePath := fmt.Sprintf("%s/test-fixtures/fileurl/%s", cwd, "cake")
source := fmt.Sprintf("file://" + sourcePath)
t.Logf("Trying to download %s", source)
config := &DownloadConfig{
Url: source,
// This should be wrong. We want to make sure we don't delete
Checksum: []byte("nope"),
Hash: HashForType("sha256"),
CopyFile: false,
}
client := NewDownloadClient(config)
// Verify that we fail to match the checksum
_, err = client.Get()
if err.Error() != "checksums didn't match expected: 6e6f7065" {
t.Fatalf("Unexpected failure; expected checksum not to match")
}
if _, err = os.Stat(sourcePath); err != nil {
t.Errorf("Could not stat source file: %s", sourcePath)
}
}

@ -0,0 +1 @@
delicious chocolate cake

@ -3,6 +3,7 @@ package artifice
import (
"fmt"
"os"
"path/filepath"
"strings"
)
@ -13,13 +14,18 @@ type Artifact struct {
}
func NewArtifact(files []string) (*Artifact, error) {
artifact := &Artifact{}
for _, f := range files {
if _, err := os.Stat(f); err != nil {
globfiles, err := filepath.Glob(f)
if err != nil {
return nil, err
}
}
artifact := &Artifact{
files: files,
for _, gf := range globfiles {
if _, err := os.Stat(gf); err != nil {
return nil, err
}
artifact.files = append(artifact.files, gf)
}
}
return artifact, nil
}

@ -68,11 +68,17 @@ builder.
### Required:
You must specify (only) one of `commit`, `discard`, or `export_path`.
- `commit` (boolean) - If true, the container will be committed to an image
rather than exported. This cannot be set if `export_path` is set.
rather than exported.
- `discard` (boolean) - Throw away the container when the build is complete.
This is useful for the [artifice
post-processor](https://packer.io/docs/post-processors/artifice.html).
- `export_path` (string) - The path where the final container will be exported
as a tar file. This cannot be set if `commit` is set to true.
as a tar file.
- `image` (string) - The base image for the Docker container that will
be started. This image will be pulled from the Docker registry if it doesn't

@ -251,8 +251,10 @@ builder and not otherwise conflicting with the qemuargs):
host port.
- `vm_name` (string) - This is the name of the image (QCOW2 or IMG) file for
the new virtual machine, without the file extension. By default this is
"packer-BUILDNAME", where "BUILDNAME" is the name of the build.
the new virtual machine. By default this is "packer-BUILDNAME.FORMAT", where
`BUILDNAME` is the name of the build and `FORMAT` matches the `format`
option, above. If you customize this you must specify the file extension or
none will be used.
- `vnc_port_min` and `vnc_port_max` (integer) - The minimum and maximum port
to use for the VNC port on the host machine which is forwarded to the VNC

@ -397,3 +397,23 @@ modify as well:
- `remote_username` - The SSH username used to access the remote machine.
- `remote_password` - The SSH password for access to the remote machine.
### Using a Floppy for Linux kickstart file or preseed
Depending on your network configuration, it may be difficult to use packer's
built-in HTTP server with ESXi. Instead, you can provide a kickstart or preseed
file by attaching a floppy disk. An example below, based on RHEL:
``` {.javascript}
{
"builders": [
{
"type":"vmware-iso",
"floppy_files": [
"folder/ks.cfg"
],
"boot_command": "<tab> text ks=floppy <enter><wait>"
}
]
}
```

Loading…
Cancel
Save