Merge branch 'master' into artifice
This commit is contained in:
commit
97f3f31d3d
50
CHANGELOG.md
50
CHANGELOG.md
|
@ -1,3 +1,53 @@
|
|||
## (Unreleased)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
* builder/docker: Now supports Download so it can be used with the file
|
||||
provisioner to download a file from a container. [GH-2585]
|
||||
* post-processor/vagrant: Like the compress post-processor, vagrant now uses a
|
||||
parallel gzip algorithm to compress vagrant boxes. [GH-2590]
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* builded/parallels: Fix interpolation in parallels_tools_guest_path [GH-2543]
|
||||
|
||||
## 0.8.5 (Aug 10, 2015)
|
||||
|
||||
FEATURES:
|
||||
|
||||
* **[Beta]** Artifice post-processor: Override packer artifacts during post-
|
||||
processing. This allows you to extract artifacts from a packer builder
|
||||
and use them with other post-processors like compress, docker, and Atlas.
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
* Many docs have been updated and corrected; big thanks to our contributors!
|
||||
* builder/openstack: Add debug logging for IP addresses used for SSH [GH-2513]
|
||||
* builder/openstack: Add option to use existing SSH keypair [GH-2512]
|
||||
* builder/openstack: Add support for Glance metadata [GH-2434]
|
||||
* builder/qemu and builder/vmware: Packer's VNC connection no longer asks for
|
||||
an exclusive connection [GH-2522]
|
||||
* provisioner/salt-masterless: Can now customize salt remote directories [GH-2519]
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* builder/amazon: Improve instance cleanup by storing id sooner [GH-2404]
|
||||
* builder/amazon: Only fetch windows password when using WinRM communicator [GH-2538]
|
||||
* builder/openstack: Support IPv6 SSH address [GH-2450]
|
||||
* builder/openstack: Track new IP address discovered during RackConnect [GH-2514]
|
||||
* builder/qemu: Add 100ms delay between VNC key events. [GH-2415]
|
||||
* post-processor/atlas: atlas_url configuration option works now [GH-2478]
|
||||
* post-processor/compress: Now supports interpolation in output config [GH-2414]
|
||||
* provisioner/powershell: Elevated runs now receive environment variables [GH-2378]
|
||||
* provisioner/salt-masterless: Clarify error messages when we can't create or
|
||||
write to the temp directory [GH-2518]
|
||||
* provisioner/salt-masterless: Copy state even if /srv/salt exists already [GH-1699]
|
||||
* provisioner/salt-masterless: Make sure /etc/salt exists before writing to it [GH-2520]
|
||||
* provisioner/winrm: Connect to the correct port when using NAT with
|
||||
VirtualBox / VMware [GH-2399]
|
||||
|
||||
Note: 0.8.3 was pulled and 0.8.4 was skipped.
|
||||
|
||||
## 0.8.2 (July 17, 2015)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
|
@ -31,7 +32,7 @@ func (c *AccessConfig) Config() (*aws.Config, error) {
|
|||
}},
|
||||
&credentials.EnvProvider{},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
|
||||
&credentials.EC2RoleProvider{},
|
||||
&ec2rolecreds.EC2RoleProvider{},
|
||||
})
|
||||
|
||||
region, err := c.Region()
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -194,8 +195,42 @@ func (c *Communicator) UploadDir(dst string, src string, exclude []string) error
|
|||
return nil
|
||||
}
|
||||
|
||||
// Download pulls a file out of a container using `docker cp`. We have a source
|
||||
// path and want to write to an io.Writer, not a file. We use - to make docker
|
||||
// cp to write to stdout, and then copy the stream to our destination io.Writer.
|
||||
func (c *Communicator) Download(src string, dst io.Writer) error {
|
||||
panic("not implemented")
|
||||
log.Printf("Downloading file from container: %s:%s", c.ContainerId, src)
|
||||
localCmd := exec.Command("docker", "cp", fmt.Sprintf("%s:%s", c.ContainerId, src), "-")
|
||||
|
||||
pipe, err := localCmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to open pipe: %s", err)
|
||||
}
|
||||
|
||||
if err = localCmd.Start(); err != nil {
|
||||
return fmt.Errorf("Failed to start download: %s", err)
|
||||
}
|
||||
|
||||
// When you use - to send docker cp to stdout it is streamed as a tar; this
|
||||
// enables it to work with directories. We don't actually support
|
||||
// directories in Download() but we still need to handle the tar format.
|
||||
archive := tar.NewReader(pipe)
|
||||
_, err = archive.Next()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to read header from tar stream: %s", err)
|
||||
}
|
||||
|
||||
numBytes, err := io.Copy(dst, archive)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to pipe download: %s", err)
|
||||
}
|
||||
log.Printf("Copied %d bytes for %s", numBytes, src)
|
||||
|
||||
if err = localCmd.Wait(); err != nil {
|
||||
return fmt.Errorf("Failed to download '%s' from container: %s", src, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// canExec tells us whether `docker exec` is supported
|
||||
|
|
|
@ -1,10 +1,129 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"crypto/sha256"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"github.com/mitchellh/packer/provisioner/file"
|
||||
"github.com/mitchellh/packer/template"
|
||||
)
|
||||
|
||||
func TestCommunicator_impl(t *testing.T) {
|
||||
var _ packer.Communicator = new(Communicator)
|
||||
}
|
||||
|
||||
func TestUploadDownload(t *testing.T) {
|
||||
ui := packer.TestUi(t)
|
||||
cache := &packer.FileCache{CacheDir: os.TempDir()}
|
||||
|
||||
tpl, err := template.Parse(strings.NewReader(dockerBuilderConfig))
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to parse config: %s", err)
|
||||
}
|
||||
|
||||
// Make sure we only run this on linux hosts
|
||||
if os.Getenv("PACKER_ACC") == "" {
|
||||
t.Skip("This test is only run with PACKER_ACC=1")
|
||||
}
|
||||
if runtime.GOOS != "linux" {
|
||||
t.Skip("This test is only supported on linux")
|
||||
}
|
||||
cmd := exec.Command("docker", "-v")
|
||||
cmd.Run()
|
||||
if !cmd.ProcessState.Success() {
|
||||
t.Error("docker command not found; please make sure docker is installed")
|
||||
}
|
||||
|
||||
// Setup the builder
|
||||
builder := &Builder{}
|
||||
warnings, err := builder.Prepare(tpl.Builders["docker"].Config)
|
||||
if err != nil {
|
||||
t.Fatalf("Error preparing configuration %s", err)
|
||||
}
|
||||
if len(warnings) > 0 {
|
||||
t.Fatal("Encountered configuration warnings; aborting")
|
||||
}
|
||||
|
||||
// Setup the provisioners
|
||||
upload := &file.Provisioner{}
|
||||
err = upload.Prepare(tpl.Provisioners[0].Config)
|
||||
if err != nil {
|
||||
t.Fatalf("Error preparing upload: %s", err)
|
||||
}
|
||||
download := &file.Provisioner{}
|
||||
err = download.Prepare(tpl.Provisioners[1].Config)
|
||||
if err != nil {
|
||||
t.Fatalf("Error preparing download: %s", err)
|
||||
}
|
||||
// Preemptive cleanup. Honestly I don't know why you would want to get rid
|
||||
// of my strawberry cake. It's so tasty! Do you not like cake? Are you a
|
||||
// cake-hater? Or are you keeping all the cake all for yourself? So selfish!
|
||||
defer os.Remove("my-strawberry-cake")
|
||||
|
||||
// Add hooks so the provisioners run during the build
|
||||
hooks := map[string][]packer.Hook{}
|
||||
hooks[packer.HookProvision] = []packer.Hook{
|
||||
&packer.ProvisionHook{
|
||||
Provisioners: []packer.Provisioner{
|
||||
upload,
|
||||
download,
|
||||
},
|
||||
},
|
||||
}
|
||||
hook := &packer.DispatchHook{Mapping: hooks}
|
||||
|
||||
// Run things
|
||||
artifact, err := builder.Run(ui, hook, cache)
|
||||
if err != nil {
|
||||
t.Fatalf("Error running build %s", err)
|
||||
}
|
||||
// Preemptive cleanup
|
||||
defer artifact.Destroy()
|
||||
|
||||
// Verify that the thing we downloaded is the same thing we sent up.
|
||||
// Complain loudly if it isn't.
|
||||
inputFile, err := ioutil.ReadFile("test-fixtures/onecakes/strawberry")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read input file: %s", err)
|
||||
}
|
||||
outputFile, err := ioutil.ReadFile("my-strawberry-cake")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read output file: %s", err)
|
||||
}
|
||||
if sha256.Sum256(inputFile) != sha256.Sum256(outputFile) {
|
||||
t.Fatalf("Input and output files do not match\n"+
|
||||
"Input:\n%s\nOutput:\n%s\n", inputFile, outputFile)
|
||||
}
|
||||
}
|
||||
|
||||
const dockerBuilderConfig = `
|
||||
{
|
||||
"builders": [
|
||||
{
|
||||
"type": "docker",
|
||||
"image": "alpine",
|
||||
"export_path": "alpine.tar",
|
||||
"run_command": ["-d", "-i", "-t", "{{.Image}}", "/bin/sh"]
|
||||
}
|
||||
],
|
||||
"provisioners": [
|
||||
{
|
||||
"type": "file",
|
||||
"source": "test-fixtures/onecakes/strawberry",
|
||||
"destination": "/strawberry-cake"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"source": "/strawberry-cake",
|
||||
"destination": "my-strawberry-cake",
|
||||
"direction": "download"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
chocolate!
|
|
@ -0,0 +1 @@
|
|||
vanilla!
|
|
@ -0,0 +1 @@
|
|||
strawberry!
|
|
@ -0,0 +1,86 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepUploadParallelsTools_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepUploadParallelsTools)
|
||||
}
|
||||
|
||||
func TestStepUploadParallelsTools(t *testing.T) {
|
||||
state := testState(t)
|
||||
state.Put("parallels_tools_path", "./step_upload_parallels_tools_test.go")
|
||||
step := new(StepUploadParallelsTools)
|
||||
step.ParallelsToolsMode = "upload"
|
||||
step.ParallelsToolsGuestPath = "/tmp/prl-lin.iso"
|
||||
step.ParallelsToolsFlavor = "lin"
|
||||
|
||||
comm := new(packer.MockCommunicator)
|
||||
state.Put("communicator", comm)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Verify
|
||||
if comm.UploadPath != "/tmp/prl-lin.iso" {
|
||||
t.Fatalf("bad: %#v", comm.UploadPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepUploadParallelsTools_interpolate(t *testing.T) {
|
||||
state := testState(t)
|
||||
state.Put("parallels_tools_path", "./step_upload_parallels_tools_test.go")
|
||||
step := new(StepUploadParallelsTools)
|
||||
step.ParallelsToolsMode = "upload"
|
||||
step.ParallelsToolsGuestPath = "/tmp/prl-{{ .Flavor }}.iso"
|
||||
step.ParallelsToolsFlavor = "win"
|
||||
|
||||
comm := new(packer.MockCommunicator)
|
||||
state.Put("communicator", comm)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Verify
|
||||
if comm.UploadPath != "/tmp/prl-win.iso" {
|
||||
t.Fatalf("bad: %#v", comm.UploadPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepUploadParallelsTools_attach(t *testing.T) {
|
||||
state := testState(t)
|
||||
state.Put("parallels_tools_path", "./step_upload_parallels_tools_test.go")
|
||||
step := new(StepUploadParallelsTools)
|
||||
step.ParallelsToolsMode = "attach"
|
||||
step.ParallelsToolsGuestPath = "/tmp/prl-lin.iso"
|
||||
step.ParallelsToolsFlavor = "lin"
|
||||
|
||||
comm := new(packer.MockCommunicator)
|
||||
state.Put("communicator", comm)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Verify
|
||||
if comm.UploadCalled {
|
||||
t.Fatal("bad")
|
||||
}
|
||||
}
|
|
@ -64,7 +64,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
|||
Exclude: []string{
|
||||
"boot_command",
|
||||
"prlctl",
|
||||
"parallel_tools_guest_path",
|
||||
"parallels_tools_guest_path",
|
||||
},
|
||||
},
|
||||
}, raws...)
|
||||
|
|
|
@ -41,7 +41,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
|||
Exclude: []string{
|
||||
"boot_command",
|
||||
"prlctl",
|
||||
"parallel_tools_guest_path",
|
||||
"parallels_tools_guest_path",
|
||||
},
|
||||
},
|
||||
}, raws...)
|
||||
|
|
|
@ -39,7 +39,7 @@ func CommHost(config *SSHConfig) func(multistep.StateBag) (string, error) {
|
|||
var ok bool
|
||||
macAddress := ""
|
||||
if macAddress, ok = vmxData["ethernet0.address"]; !ok || macAddress == "" {
|
||||
if macAddress, ok = vmxData["ethernet0.generatedAddress"]; !ok || macAddress == "" {
|
||||
if macAddress, ok = vmxData["ethernet0.generatedaddress"]; !ok || macAddress == "" {
|
||||
return "", errors.New("couldn't find MAC address in VMX")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
// This step cleans up the VMX by removing or changing this prior to
|
||||
|
@ -51,8 +52,8 @@ func (s StepCleanVMX) Run(state multistep.StateBag) multistep.StepAction {
|
|||
|
||||
ui.Message("Detaching ISO from CD-ROM device...")
|
||||
|
||||
vmxData[ide+"deviceType"] = "cdrom-raw"
|
||||
vmxData[ide+"fileName"] = "auto detect"
|
||||
vmxData[ide+"devicetype"] = "cdrom-raw"
|
||||
vmxData[ide+"filename"] = "auto detect"
|
||||
}
|
||||
|
||||
ui.Message("Disabling VNC server...")
|
||||
|
|
|
@ -61,8 +61,8 @@ func TestStepCleanVMX_floppyPath(t *testing.T) {
|
|||
Value string
|
||||
}{
|
||||
{"floppy0.present", "FALSE"},
|
||||
{"floppy0.fileType", ""},
|
||||
{"floppy0.fileName", ""},
|
||||
{"floppy0.filetype", ""},
|
||||
{"floppy0.filename", ""},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
@ -109,9 +109,9 @@ func TestStepCleanVMX_isoPath(t *testing.T) {
|
|||
Key string
|
||||
Value string
|
||||
}{
|
||||
{"ide0:0.fileName", "auto detect"},
|
||||
{"ide0:0.deviceType", "cdrom-raw"},
|
||||
{"ide0:1.fileName", "bar"},
|
||||
{"ide0:0.filename", "auto detect"},
|
||||
{"ide0:0.devicetype", "cdrom-raw"},
|
||||
{"ide0:1.filename", "bar"},
|
||||
{"foo", "bar"},
|
||||
}
|
||||
|
||||
|
@ -130,12 +130,12 @@ func TestStepCleanVMX_isoPath(t *testing.T) {
|
|||
|
||||
const testVMXFloppyPath = `
|
||||
floppy0.present = "TRUE"
|
||||
floppy0.fileType = "file"
|
||||
floppy0.filetype = "file"
|
||||
`
|
||||
|
||||
const testVMXISOPath = `
|
||||
ide0:0.deviceType = "cdrom-image"
|
||||
ide0:0.fileName = "foo"
|
||||
ide0:1.fileName = "bar"
|
||||
ide0:0.devicetype = "cdrom-image"
|
||||
ide0:0.filename = "foo"
|
||||
ide0:1.filename = "bar"
|
||||
foo = "bar"
|
||||
`
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
|
@ -52,6 +53,7 @@ func (s *StepConfigureVMX) Run(state multistep.StateBag) multistep.StepAction {
|
|||
// Set custom data
|
||||
for k, v := range s.CustomData {
|
||||
log.Printf("Setting VMX: '%s' = '%s'", k, v)
|
||||
k = strings.ToLower(k)
|
||||
vmxData[k] = v
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
func ParseVMX(contents string) map[string]string {
|
||||
results := make(map[string]string)
|
||||
|
||||
lineRe := regexp.MustCompile(`^(.+?)\s*=\s*"?(.*?)"?\s*$`)
|
||||
lineRe := regexp.MustCompile(`^(.+?)\s*=\s*"(.*?)"\s*$`)
|
||||
|
||||
for _, line := range strings.Split(contents, "\n") {
|
||||
matches := lineRe.FindStringSubmatch(line)
|
||||
|
@ -25,7 +25,8 @@ func ParseVMX(contents string) map[string]string {
|
|||
continue
|
||||
}
|
||||
|
||||
results[matches[1]] = matches[2]
|
||||
key := strings.ToLower(matches[1])
|
||||
results[key] = matches[2]
|
||||
}
|
||||
|
||||
return results
|
||||
|
@ -42,22 +43,9 @@ func EncodeVMX(contents map[string]string) string {
|
|||
i++
|
||||
}
|
||||
|
||||
// a list of VMX key fragments that should not be wrapped in quotes,
|
||||
// fragments because multiple disks can use the virtualSSD suffix
|
||||
noQuotes := []string {
|
||||
"virtualSSD",
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
pat := "%s = \"%s\"\n"
|
||||
for _, q := range noQuotes {
|
||||
if strings.Contains(k, q) {
|
||||
pat = "%s = %s\n"
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf(pat, k, contents[k]))
|
||||
buf.WriteString(fmt.Sprintf("%s = \"%s\"\n", k, contents[k]))
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
|
|
|
@ -38,14 +38,14 @@ func (s *StepCloneVMX) Run(state multistep.StateBag) multistep.StepAction {
|
|||
}
|
||||
|
||||
var diskName string
|
||||
if _, ok := vmxData["scsi0:0.fileName"]; ok {
|
||||
diskName = vmxData["scsi0:0.fileName"]
|
||||
if _, ok := vmxData["scsi0:0.filename"]; ok {
|
||||
diskName = vmxData["scsi0:0.filename"]
|
||||
}
|
||||
if _, ok := vmxData["sata0:0.fileName"]; ok {
|
||||
diskName = vmxData["sata0:0.fileName"]
|
||||
if _, ok := vmxData["sata0:0.filename"]; ok {
|
||||
diskName = vmxData["sata0:0.filename"]
|
||||
}
|
||||
if _, ok := vmxData["ide0:0.fileName"]; ok {
|
||||
diskName = vmxData["ide0:0.fileName"]
|
||||
if _, ok := vmxData["ide0:0.filename"]; ok {
|
||||
diskName = vmxData["ide0:0.filename"]
|
||||
}
|
||||
if diskName == "" {
|
||||
err := fmt.Errorf("Root disk filename could not be found!")
|
||||
|
|
|
@ -3,14 +3,23 @@ package vagrant
|
|||
import (
|
||||
"archive/tar"
|
||||
"compress/flate"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/klauspost/pgzip"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidCompressionLevel is returned when the compression level passed
|
||||
// to gzip is not in the expected range. See compress/flate for details.
|
||||
ErrInvalidCompressionLevel = fmt.Errorf(
|
||||
"Invalid compression level. Expected an integer from -1 to 9.")
|
||||
)
|
||||
|
||||
// Copies a file by copying the contents of the file to another place.
|
||||
|
@ -60,10 +69,10 @@ func DirToBox(dst, dir string, ui packer.Ui, level int) error {
|
|||
}
|
||||
defer dstF.Close()
|
||||
|
||||
var dstWriter io.Writer = dstF
|
||||
var dstWriter io.WriteCloser = dstF
|
||||
if level != flate.NoCompression {
|
||||
log.Printf("Compressing with gzip compression level: %d", level)
|
||||
gzipWriter, err := gzip.NewWriterLevel(dstWriter, level)
|
||||
gzipWriter, err := makePgzipWriter(dstWriter, level)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -143,3 +152,12 @@ func WriteMetadata(dir string, contents interface{}) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func makePgzipWriter(output io.WriteCloser, compressionLevel int) (io.WriteCloser, error) {
|
||||
gzipWriter, err := pgzip.NewWriterLevel(output, compressionLevel)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidCompressionLevel
|
||||
}
|
||||
gzipWriter.SetConcurrency(500000, runtime.GOMAXPROCS(-1))
|
||||
return gzipWriter, nil
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ package main
|
|||
var GitCommit string
|
||||
|
||||
// The main version number that is being run at the moment.
|
||||
const Version = "0.8.3"
|
||||
const Version = "0.8.6"
|
||||
|
||||
// A pre-release marker for the version. If this is "" (empty string)
|
||||
// then it means that it is a final release. Otherwise, this is a pre-release
|
||||
// such as "dev" (in development), "beta", "rc1", etc.
|
||||
const VersionPrerelease = ""
|
||||
const VersionPrerelease = "dev"
|
||||
|
|
|
@ -393,3 +393,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>"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
---
|
||||
description: |
|
||||
The Atlas post-processor for Packer receives an artifact from a Packer build and
|
||||
uploads it to Atlas. Atlas hosts and serves artifacts, allowing you to version
|
||||
and distribute them in a simple way.
|
||||
The artifice post-processor overrides the artifact list from an upstream builder
|
||||
or post-processor. All downstream post-processors will see the new artifacts you
|
||||
specify. The primary use-case is to build artifacts inside a packer builder --
|
||||
for example, spinning up an EC2 instance to build a docker container -- and then
|
||||
extracting the docker container and throwing away the EC2 instance.
|
||||
layout: docs
|
||||
page_title: 'Atlas Post-Processor'
|
||||
...
|
||||
|
@ -45,8 +47,8 @@ Artifice helps you tie together a few other packer features:
|
|||
- Additional post-processors, which push the artifact to Atlas, Docker
|
||||
hub, etc.
|
||||
|
||||
You will want to perform as much work as possible inside the VM. Ideally
|
||||
the only other post-processor you need after artifice is one that uploads your
|
||||
You will want to perform as much work as possible inside the VM. Ideally the
|
||||
only other post-processor you need after artifice is one that uploads your
|
||||
artifact to the appropriate repository.
|
||||
|
||||
## Configuration
|
||||
|
@ -64,13 +66,14 @@ The configuration allows you to specify which files comprise your artifact.
|
|||
|
||||
This minimal example:
|
||||
|
||||
1. Spins up a cloned VMware virtual machine
|
||||
2. Installs a [consul](https://consul.io/) release
|
||||
3. Downloads the consul binary
|
||||
4. Packages it into a `.tar.gz` file
|
||||
5. Uploads it to Atlas.
|
||||
1. Spins up a cloned VMware virtual machine
|
||||
2. Installs a [consul](https://consul.io/) release
|
||||
3. Downloads the consul binary
|
||||
4. Packages it into a `.tar.gz` file
|
||||
5. Uploads it to Atlas.
|
||||
|
||||
VMX is a fast way to build and test locally, but you can easily substitute another builder.
|
||||
VMX is a fast way to build and test locally, but you can easily substitute
|
||||
another builder.
|
||||
|
||||
``` {.javascript}
|
||||
{
|
||||
|
@ -143,5 +146,5 @@ artifact (the vmx file in this case) and it will not have the desired result.
|
|||
}
|
||||
]
|
||||
|
||||
You can create multiple post-processor chains to handle multiple builders (for example,
|
||||
building linux and windows binaries during the same build).
|
||||
You can create multiple post-processor chains to handle multiple builders (for
|
||||
example, building linux and windows binaries during the same build).
|
||||
|
|
|
@ -27,8 +27,8 @@ you will need to specify the `output` option.
|
|||
detected packer defaults to `.tar.gz` behavior but will not change
|
||||
the filename.
|
||||
|
||||
You can use `{{.BuildName}}` and `{{.BuilderType}}` in your output path.
|
||||
If you are executing multiple builders in parallel you should make sure
|
||||
You can use `{{.BuildName}}` and `{{.BuilderType}}` in your output path. If
|
||||
you are executing multiple builders in parallel you should make sure
|
||||
`output` is unique for each one. For example `packer_{{.BuildName}}.zip`.
|
||||
|
||||
- `compression_level` (integer) - Specify the compression level, for
|
||||
|
|
Loading…
Reference in New Issue