diff --git a/CHANGELOG.md b/CHANGELOG.md index f9ac6e548..115ed3886 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,31 @@ -## 0.4.1 (unreleased) +## 0.5.0 (unreleased) + + + +## 0.4.1 (December 7, 2013) + +IMPROVEMENTS: + +* builder/amazon/ebs: New option allows associating a public IP with + non-default VPC instances. [GH-660] +* builder/openstack: A "proxy\_url" setting was added to define an HTTP + proxy to use when building with this builder. [GH-637] BUG FIXES: * core: Don't change background color on CLI anymore, making things look a tad nicer in some terminals. +* core: multiple ISO URLs works properly in all builders. [GH-683] +* builder/amazon/chroot: Block when obtaining file lock to allow + parallel builds. [GH-689] +* builder/amazon/instance: Add location flag to upload bundle command + so that building AMIs works out of us-east-1 [GH-679] +* builder/vmware: Cleanup of VMX keys works properly so cd-rom won't + get stuck with ISO. [GH-685] +* builder/vmware: File cleanup is more resilient to file delete races + with the operating system. [GH-675] +* provisioner/puppet-masterless: Check for hiera config path existence + properly. [GH-656] ## 0.4.0 (November 19, 2013) diff --git a/README.md b/README.md index 76d3368ce..ef498b853 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ For some additional dependencies, Go needs [Mercurial](http://mercurial.selenic. and [Bazaar](http://bazaar.canonical.com/en/) to be installed. Packer itself doesn't require these, but a dependency of a dependency does. -You'll also need [`gox`](https://github.com/mitchellh/packer) +You'll also need [`gox`](https://github.com/mitchellh/gox) to compile packer. You can install that with: ``` diff --git a/builder/amazon/chroot/lockfile_unix.go b/builder/amazon/chroot/lockfile_unix.go index f84ea0d57..43e92af21 100644 --- a/builder/amazon/chroot/lockfile_unix.go +++ b/builder/amazon/chroot/lockfile_unix.go @@ -3,7 +3,6 @@ package chroot import ( - "errors" "os" "syscall" ) @@ -14,13 +13,8 @@ const LOCK_NB = 4 const LOCK_UN = 8 func lockFile(f *os.File) error { - err := syscall.Flock(int(f.Fd()), LOCK_EX|LOCK_NB) + err := syscall.Flock(int(f.Fd()), LOCK_EX) if err != nil { - errno, ok := err.(syscall.Errno) - if ok && errno == syscall.EWOULDBLOCK { - return errors.New("file already locked") - } - return err } diff --git a/builder/amazon/chroot/step_flock.go b/builder/amazon/chroot/step_flock.go index 989bd3930..9f7ca54b8 100644 --- a/builder/amazon/chroot/step_flock.go +++ b/builder/amazon/chroot/step_flock.go @@ -39,7 +39,7 @@ func (s *StepFlock) Run(state multistep.StateBag) multistep.StepAction { // LOCK! if err := lockFile(f); err != nil { - err := fmt.Errorf("Error creating lock: %s", err) + err := fmt.Errorf("Error obtaining lock: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt diff --git a/builder/amazon/common/run_config.go b/builder/amazon/common/run_config.go index 208266518..75faed662 100644 --- a/builder/amazon/common/run_config.go +++ b/builder/amazon/common/run_config.go @@ -11,20 +11,21 @@ import ( // RunConfig contains configuration for running an instance from a source // AMI and details on how to access that launched image. type RunConfig struct { - SourceAmi string `mapstructure:"source_ami"` - IamInstanceProfile string `mapstructure:"iam_instance_profile"` - InstanceType string `mapstructure:"instance_type"` - UserData string `mapstructure:"user_data"` - UserDataFile string `mapstructure:"user_data_file"` - RawSSHTimeout string `mapstructure:"ssh_timeout"` - SSHUsername string `mapstructure:"ssh_username"` - SSHPort int `mapstructure:"ssh_port"` - SecurityGroupId string `mapstructure:"security_group_id"` - SecurityGroupIds []string `mapstructure:"security_group_ids"` - SubnetId string `mapstructure:"subnet_id"` - TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"` - VpcId string `mapstructure:"vpc_id"` - AvailabilityZone string `mapstructure:"availability_zone"` + SourceAmi string `mapstructure:"source_ami"` + IamInstanceProfile string `mapstructure:"iam_instance_profile"` + InstanceType string `mapstructure:"instance_type"` + UserData string `mapstructure:"user_data"` + UserDataFile string `mapstructure:"user_data_file"` + RawSSHTimeout string `mapstructure:"ssh_timeout"` + SSHUsername string `mapstructure:"ssh_username"` + SSHPort int `mapstructure:"ssh_port"` + SecurityGroupId string `mapstructure:"security_group_id"` + SecurityGroupIds []string `mapstructure:"security_group_ids"` + SubnetId string `mapstructure:"subnet_id"` + AssociatePublicIpAddress bool `mapstructure:"associate_public_ip_address"` + TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"` + VpcId string `mapstructure:"vpc_id"` + AvailabilityZone string `mapstructure:"availability_zone"` // Unexported fields that are calculated from others sshTimeout time.Duration diff --git a/builder/amazon/common/ssh.go b/builder/amazon/common/ssh.go index 5e7d8872d..6756c62e7 100644 --- a/builder/amazon/common/ssh.go +++ b/builder/amazon/common/ssh.go @@ -20,7 +20,11 @@ func SSHAddress(e *ec2.EC2, port int) func(multistep.StateBag) (string, error) { if i.DNSName != "" { host = i.DNSName } else if i.VpcId != "" { - host = i.PrivateIpAddress + if i.PublicIpAddress != "" { + host = i.PublicIpAddress + } else { + host = i.PrivateIpAddress + } } if host != "" { diff --git a/builder/amazon/common/step_run_source_instance.go b/builder/amazon/common/step_run_source_instance.go index 9d92c226c..77d330a21 100644 --- a/builder/amazon/common/step_run_source_instance.go +++ b/builder/amazon/common/step_run_source_instance.go @@ -10,16 +10,17 @@ import ( ) type StepRunSourceInstance struct { - Debug bool - ExpectedRootDevice string - InstanceType string - UserData string - UserDataFile string - SourceAMI string - IamInstanceProfile string - SubnetId string - AvailabilityZone string - BlockDevices BlockDevices + Debug bool + ExpectedRootDevice string + InstanceType string + UserData string + UserDataFile string + SourceAMI string + IamInstanceProfile string + SubnetId string + AssociatePublicIpAddress bool + AvailabilityZone string + BlockDevices BlockDevices instance *ec2.Instance } @@ -47,17 +48,18 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi } runOpts := &ec2.RunInstances{ - KeyName: keyName, - ImageId: s.SourceAMI, - InstanceType: s.InstanceType, - UserData: []byte(userData), - MinCount: 0, - MaxCount: 0, - SecurityGroups: securityGroups, - IamInstanceProfile: s.IamInstanceProfile, - SubnetId: s.SubnetId, - BlockDevices: s.BlockDevices.BuildLaunchDevices(), - AvailZone: s.AvailabilityZone, + KeyName: keyName, + ImageId: s.SourceAMI, + InstanceType: s.InstanceType, + UserData: []byte(userData), + MinCount: 0, + MaxCount: 0, + SecurityGroups: securityGroups, + IamInstanceProfile: s.IamInstanceProfile, + SubnetId: s.SubnetId, + AssociatePublicIpAddress: s.AssociatePublicIpAddress, + BlockDevices: s.BlockDevices.BuildLaunchDevices(), + AvailZone: s.AvailabilityZone, } ui.Say("Launching a source AWS instance...") @@ -114,6 +116,10 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi ui.Message(fmt.Sprintf("Public DNS: %s", s.instance.DNSName)) } + if s.instance.PublicIpAddress != "" { + ui.Message(fmt.Sprintf("Public IP: %s", s.instance.PublicIpAddress)) + } + if s.instance.PrivateIpAddress != "" { ui.Message(fmt.Sprintf("Private IP: %s", s.instance.PrivateIpAddress)) } diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 5d68f9470..e58392f84 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -93,16 +93,17 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe VpcId: b.config.VpcId, }, &awscommon.StepRunSourceInstance{ - Debug: b.config.PackerDebug, - ExpectedRootDevice: "ebs", - InstanceType: b.config.InstanceType, - UserData: b.config.UserData, - UserDataFile: b.config.UserDataFile, - SourceAMI: b.config.SourceAmi, - IamInstanceProfile: b.config.IamInstanceProfile, - SubnetId: b.config.SubnetId, - AvailabilityZone: b.config.AvailabilityZone, - BlockDevices: b.config.BlockDevices, + Debug: b.config.PackerDebug, + ExpectedRootDevice: "ebs", + InstanceType: b.config.InstanceType, + UserData: b.config.UserData, + UserDataFile: b.config.UserDataFile, + SourceAMI: b.config.SourceAmi, + IamInstanceProfile: b.config.IamInstanceProfile, + SubnetId: b.config.SubnetId, + AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, + AvailabilityZone: b.config.AvailabilityZone, + BlockDevices: b.config.BlockDevices, }, &common.StepConnectSSH{ SSHAddress: awscommon.SSHAddress(ec2conn, b.config.SSHPort), diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 455a7cd01..db1d6c28e 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -74,6 +74,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { "-s {{.SecretKey}} " + "-d {{.BundleDirectory}} " + "--batch " + + "--location {{.Region}} " + "--retry" } @@ -196,16 +197,17 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe VpcId: b.config.VpcId, }, &awscommon.StepRunSourceInstance{ - Debug: b.config.PackerDebug, - ExpectedRootDevice: "instance-store", - InstanceType: b.config.InstanceType, - IamInstanceProfile: b.config.IamInstanceProfile, - UserData: b.config.UserData, - UserDataFile: b.config.UserDataFile, - SourceAMI: b.config.SourceAmi, - SubnetId: b.config.SubnetId, - AvailabilityZone: b.config.AvailabilityZone, - BlockDevices: b.config.BlockDevices, + Debug: b.config.PackerDebug, + ExpectedRootDevice: "instance-store", + InstanceType: b.config.InstanceType, + IamInstanceProfile: b.config.IamInstanceProfile, + UserData: b.config.UserData, + UserDataFile: b.config.UserDataFile, + SourceAMI: b.config.SourceAmi, + SubnetId: b.config.SubnetId, + AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, + AvailabilityZone: b.config.AvailabilityZone, + BlockDevices: b.config.BlockDevices, }, &common.StepConnectSSH{ SSHAddress: awscommon.SSHAddress(ec2conn, b.config.SSHPort), diff --git a/builder/amazon/instance/step_upload_bundle.go b/builder/amazon/instance/step_upload_bundle.go index e002ff43d..ec654aa61 100644 --- a/builder/amazon/instance/step_upload_bundle.go +++ b/builder/amazon/instance/step_upload_bundle.go @@ -11,6 +11,7 @@ type uploadCmdData struct { BucketName string BundleDirectory string ManifestPath string + Region string SecretKey string } @@ -23,12 +24,20 @@ func (s *StepUploadBundle) Run(state multistep.StateBag) multistep.StepAction { manifestPath := state.Get("manifest_path").(string) ui := state.Get("ui").(packer.Ui) - var err error + region, err := config.Region() + if err != nil { + err := fmt.Errorf("Error retrieving region: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + config.BundleUploadCommand, err = config.tpl.Process(config.BundleUploadCommand, uploadCmdData{ AccessKey: config.AccessKey, BucketName: config.S3Bucket, BundleDirectory: config.BundleDestination, ManifestPath: manifestPath, + Region: region.Name, SecretKey: config.SecretKey, }) if err != nil { diff --git a/builder/openstack/access_config.go b/builder/openstack/access_config.go index 82fcee185..947e58854 100644 --- a/builder/openstack/access_config.go +++ b/builder/openstack/access_config.go @@ -4,6 +4,8 @@ import ( "fmt" "github.com/mitchellh/packer/packer" "github.com/rackspace/gophercloud" + "net/http" + "net/url" "os" ) @@ -14,6 +16,7 @@ type AccessConfig struct { Project string `mapstructure:"project"` Provider string `mapstructure:"provider"` RawRegion string `mapstructure:"region"` + ProxyUrl string `mapstructure:"proxy_url"` } // Auth returns a valid Auth object for access to openstack services, or @@ -23,6 +26,7 @@ func (c *AccessConfig) Auth() (gophercloud.AccessProvider, error) { password := c.Password project := c.Project provider := c.Provider + proxy := c.ProxyUrl if username == "" { username = os.Getenv("SDK_USERNAME") @@ -47,6 +51,19 @@ func (c *AccessConfig) Auth() (gophercloud.AccessProvider, error) { authoptions.TenantName = project } + // For corporate networks it may be the case where we want our API calls + // to be sent through a separate HTTP proxy than external traffic. + if proxy != "" { + url, err := url.Parse(proxy) + if err != nil { + return nil, err + } + + // The gophercloud.Context has a UseCustomClient method which + // would allow us to override with a new instance of http.Client. + http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(url)} + } + return gophercloud.Authenticate(provider, authoptions) } diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index 83169f38e..065b2436a 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -217,7 +217,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { if !(b.config.Format == "qcow2" || b.config.Format == "raw") { errs = packer.MultiErrorAppend( - errs, errors.New("invalid format, only 'qcow2' or 'img' are allowed")) + errs, errors.New("invalid format, only 'qcow2' or 'raw' are allowed")) } if !(b.config.Accelerator == "kvm" || b.config.Accelerator == "xen") { diff --git a/builder/vmware/driver_esx5.go b/builder/vmware/driver_esx5.go index 825092abd..f23978a32 100644 --- a/builder/vmware/driver_esx5.go +++ b/builder/vmware/driver_esx5.go @@ -314,7 +314,8 @@ func (d *ESX5Driver) checkGuestIPHackEnabled() error { } if record["IntValue"] != "1" { - return errors.New("GuestIPHack is required, enable with:\n" + + return errors.New( + "GuestIPHack is required, enable by running this on the ESX machine:\n" + "esxcli system settings advanced set -o /Net/GuestIPHack -i 1") } diff --git a/builder/vmware/step_clean_files.go b/builder/vmware/step_clean_files.go index cf78d45dc..7b6eaa8b5 100644 --- a/builder/vmware/step_clean_files.go +++ b/builder/vmware/step_clean_files.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" + "os" "path/filepath" ) @@ -48,8 +49,11 @@ func (stepCleanFiles) Run(state multistep.StateBag) multistep.StepAction { if !keep { ui.Message(fmt.Sprintf("Deleting: %s", path)) if err = dir.Remove(path); err != nil { - state.Put("error", err) - return multistep.ActionHalt + // Only report the error if the file still exists + if _, serr := os.Stat(path); serr == nil || !os.IsNotExist(serr) { + state.Put("error", err) + return multistep.ActionHalt + } } } } diff --git a/builder/vmware/step_clean_vmx.go b/builder/vmware/step_clean_vmx.go index c8a66c5e0..a40855d41 100644 --- a/builder/vmware/step_clean_vmx.go +++ b/builder/vmware/step_clean_vmx.go @@ -55,12 +55,12 @@ func (s stepCleanVMX) Run(state multistep.StateBag) multistep.StepAction { continue } - filenameKey := match + ".filename" + filenameKey := match + "filename" if filename, ok := vmxData[filenameKey]; ok { if filename == isoPath { // Change the CD-ROM device back to auto-detect to eject vmxData[filenameKey] = "auto detect" - vmxData[match+".devicetype"] = "cdrom-raw" + vmxData[match+"devicetype"] = "cdrom-raw" } } } diff --git a/common/config.go b/common/config.go index 460eeabc7..a0204eed2 100644 --- a/common/config.go +++ b/common/config.go @@ -105,21 +105,21 @@ func DownloadableURL(original string) (string, error) { url.Path = strings.Replace(url.Path, `\`, `/`, -1) } - if _, err := os.Stat(url.Path); err != nil { - return "", err - } + // Only do the filepath transformations if the file appears + // to actually exist. + if _, err := os.Stat(url.Path); err == nil { + url.Path, err = filepath.Abs(url.Path) + if err != nil { + return "", err + } - url.Path, err = filepath.Abs(url.Path) - if err != nil { - return "", err - } + url.Path, err = filepath.EvalSymlinks(url.Path) + if err != nil { + return "", err + } - url.Path, err = filepath.EvalSymlinks(url.Path) - if err != nil { - return "", err + url.Path = filepath.Clean(url.Path) } - - url.Path = filepath.Clean(url.Path) } // Make sure it is lowercased diff --git a/common/config_test.go b/common/config_test.go index ea994de51..c58c105e6 100644 --- a/common/config_test.go +++ b/common/config_test.go @@ -144,8 +144,8 @@ func TestDownloadableURL_FilePaths(t *testing.T) { for _, prefix := range []string{"", "file://"} { // Nonexistent file _, err = DownloadableURL(prefix + "i/dont/exist") - if err == nil { - t.Fatal("expected err") + if err != nil { + t.Fatalf("err: %s", err) } // Good file diff --git a/packer/version.go b/packer/version.go index 44c22cf4b..6a12da5b8 100644 --- a/packer/version.go +++ b/packer/version.go @@ -10,7 +10,7 @@ import ( var GitCommit string // The version of packer. -const Version = "0.4.1" +const Version = "0.5.0" // Any pre-release marker for the version. If this is "" (empty string), // then it means that it is a final release. Otherwise, this is the diff --git a/provisioner/puppet-masterless/provisioner.go b/provisioner/puppet-masterless/provisioner.go index 263c3beac..4c19526d2 100644 --- a/provisioner/puppet-masterless/provisioner.go +++ b/provisioner/puppet-masterless/provisioner.go @@ -152,7 +152,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { // Validation if p.config.HieraConfigPath != "" { - info, err := os.Stat(p.config.ManifestFile) + info, err := os.Stat(p.config.HieraConfigPath) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("hiera_config_path is invalid: %s", err)) diff --git a/website/source/docs/builders/amazon-chroot.html.markdown b/website/source/docs/builders/amazon-chroot.html.markdown index 3ea0e456c..a1ef7a0ae 100644 --- a/website/source/docs/builders/amazon-chroot.html.markdown +++ b/website/source/docs/builders/amazon-chroot.html.markdown @@ -210,40 +210,3 @@ prevent packages installed by your provisioners from starting services: ] } - -## Using an IAM Instance Profile - -If AWS keys are not specified in the template or through environment variables -Packer will use credentials provided by the instance's IAM profile, if it has one. - -The following policy document provides the minimal set permissions necessary for Packer to work: - -
-{
-  "Statement": [{
-      "Effect": "Allow",
-      "Action" : [
-        "ec2:AttachVolume",
-        "ec2:CreateVolume",
-        "ec2:DeleteVolume",
-        "ec2:DescribeVolumes",
-        "ec2:DetachVolume",
-
-        "ec2:DescribeInstances",
-
-        "ec2:CreateSnapshot",
-        "ec2:DeleteSnapshot",
-        "ec2:DescribeSnapshots",
-
-        "ec2:DescribeImages",
-        "ec2:RegisterImage",
-
-        "ec2:CreateTags"
-      ],
-      "Resource" : "*"
-  }]
-}
-
- -Depending on what setting you use the following Actions might have to be allowed as well: -* `ec2:ModifyImageAttribute` when using `ami_description` diff --git a/website/source/docs/builders/amazon-ebs.html.markdown b/website/source/docs/builders/amazon-ebs.html.markdown index a050314a0..96177bfb9 100644 --- a/website/source/docs/builders/amazon-ebs.html.markdown +++ b/website/source/docs/builders/amazon-ebs.html.markdown @@ -111,6 +111,10 @@ Optional: * `subnet_id` (string) - If using VPC, the ID of the subnet, such as "subnet-12345def", where Packer will launch the EC2 instance. +* `associate_public_ip_address` (bool) - If using a non-default VPC, public + IP addresses are not provided by default. If this is toggled, your new + instance will get a Public IP. + * `tags` (object of key/value strings) - Tags applied to the AMI. * `user_data` (string) - User data to apply when launching the instance. diff --git a/website/source/docs/builders/amazon-instance.html.markdown b/website/source/docs/builders/amazon-instance.html.markdown index b2caf1371..42e34e48b 100644 --- a/website/source/docs/builders/amazon-instance.html.markdown +++ b/website/source/docs/builders/amazon-instance.html.markdown @@ -150,6 +150,10 @@ Optional: * `subnet_id` (string) - If using VPC, the ID of the subnet, such as "subnet-12345def", where Packer will launch the EC2 instance. +* `associate_public_ip_address` (bool) - If using a non-default VPC, public + IP addresses are not provided by default. If this is toggled, your new + instance will get a Public IP. + * `tags` (object of key/value strings) - Tags applied to the AMI. * `user_data` (string) - User data to apply when launching the instance. @@ -269,6 +273,7 @@ sudo -n ec2-upload-bundle \ -s {{.SecretKey}} \ -d {{.BundleDirectory}} \ --batch \ + --location {{.Region}} \ --retry ``` diff --git a/website/source/docs/builders/amazon.html.markdown b/website/source/docs/builders/amazon.html.markdown index 604f2489a..e4e15f886 100644 --- a/website/source/docs/builders/amazon.html.markdown +++ b/website/source/docs/builders/amazon.html.markdown @@ -30,3 +30,40 @@ AMI. Packer supports the following builders at the moment: amazon-ebs builder. It is much easier to use and Amazon generally recommends EBS-backed images nowadays. + +## Using an IAM Instance Profile + +If AWS keys are not specified in the template or through environment variables +Packer will use credentials provided by the instance's IAM profile, if it has one. + +The following policy document provides the minimal set permissions necessary for Packer to work: + +
+{
+  "Statement": [{
+      "Effect": "Allow",
+      "Action" : [
+        "ec2:AttachVolume",
+        "ec2:CreateVolume",
+        "ec2:DeleteVolume",
+        "ec2:DescribeVolumes",
+        "ec2:DetachVolume",
+
+        "ec2:DescribeInstances",
+
+        "ec2:CreateSnapshot",
+        "ec2:DeleteSnapshot",
+        "ec2:DescribeSnapshots",
+
+        "ec2:DescribeImages",
+        "ec2:RegisterImage",
+
+        "ec2:CreateTags"
+      ],
+      "Resource" : "*"
+  }]
+}
+
+ +Depending on what setting you use the following Actions might have to be allowed as well: +* `ec2:ModifyImageAttribute` when using `ami_description` diff --git a/website/source/docs/builders/openstack.html.markdown b/website/source/docs/builders/openstack.html.markdown index 441f8a7c9..a9644367b 100644 --- a/website/source/docs/builders/openstack.html.markdown +++ b/website/source/docs/builders/openstack.html.markdown @@ -59,7 +59,7 @@ Optional: * `ssh_timeout` (string) - The time to wait for SSH to become available before timing out. The format of this value is a duration such as "5s" - or "5m". The default SSH timeout is "1m". + or "1m". The default SSH timeout is "5m". * `ssh_username` (string) - The username to use in order to communicate over SSH to the running server. The default is "root". diff --git a/website/source/docs/builders/qemu.html.markdown b/website/source/docs/builders/qemu.html.markdown index cfcd2601e..96f06b9cf 100644 --- a/website/source/docs/builders/qemu.html.markdown +++ b/website/source/docs/builders/qemu.html.markdown @@ -115,7 +115,7 @@ Optional: commands or kickstart type scripts must have proper adjustments for resulting device names. The Qemu builder uses "virtio" by default. -* `format` (string) - Either "qcow2" or "img", this specifies the output +* `format` (string) - Either "qcow2" or "raw", this specifies the output format of the virtual machine image. This defaults to "qcow2". * `headless` (bool) - Packer defaults to building virtual machines by diff --git a/website/source/docs/builders/vmware.html.markdown b/website/source/docs/builders/vmware.html.markdown index b1086ee25..e4da7dff8 100644 --- a/website/source/docs/builders/vmware.html.markdown +++ b/website/source/docs/builders/vmware.html.markdown @@ -87,7 +87,8 @@ Optional: The default is "1", which corresponds to a growable virtual disk split in 2GB files. This option is for advanced usage, modify only if you know what you're doing. For more information, please consult the - [Virtual Disk Manager User's Guide](http://www.vmware.com/pdf/VirtualDiskManager.pdf). + [Virtual Disk Manager User's Guide](http://www.vmware.com/pdf/VirtualDiskManager.pdf) + for desktop VMware clients. For ESXi, refer to the proper ESXi documentation. * `floppy_files` (array of strings) - A list of files to put onto a floppy disk that is attached when the VM is booted for the first time. This is diff --git a/website/source/intro/getting-started/build-image.html.markdown b/website/source/intro/getting-started/build-image.html.markdown index 7e91de208..e37f56664 100644 --- a/website/source/intro/getting-started/build-image.html.markdown +++ b/website/source/intro/getting-started/build-image.html.markdown @@ -46,10 +46,14 @@ briefly. Create a file `example.json` and fill it with the following contents:
 {
+  "variables": {
+    "aws_access_key": "",
+    "aws_secret_key": ""
+  },
   "builders": [{
     "type": "amazon-ebs",
-    "access_key": "YOUR KEY HERE",
-    "secret_key": "YOUR SECRET KEY HERE",
+    "access_key": "{{user `aws_access_key`}}",
+    "secret_key": "{{user `aws_secret_key`}}",
     "region": "us-east-1",
     "source_ami": "ami-de0d9eb7",
     "instance_type": "t1.micro",
@@ -59,9 +63,11 @@ briefly. Create a file `example.json` and fill it with the following contents:
 }
 
-Please fill in the `access_key` and `secret_key` with the proper values -for your account. Your security credentials can be found on -[this page](https://console.aws.amazon.com/iam/home?#security_credential). +When building, you'll pass in the `aws_access_key` and `aws_access_key` as +a [user variable](/docs/templates/user-variables.html), keeping your secret +keys out of the template. You can create security credentials +on [this page](https://console.aws.amazon.com/iam/home?#security_credential). +An example IAM policy document can be found in the [Amazon EC2 builder docs](/docs/builders/amazon.html). This is a basic template that is ready-to-go. It should be immediately recognizable as a normal, basic JSON object. Within the object, the `builders` section @@ -106,7 +112,10 @@ should look similar to below. Note that this process typically takes a few minutes. ``` -$ packer build example.json +$ packer build \ + -var 'aws_access_key=YOUR ACCESS KEY' \ + -var 'aws_secret_key=YOUR SECRET KEY' \ + example.json ==> amazon-ebs: amazon-ebs output will be in this color. ==> amazon-ebs: Creating temporary keypair for this instance... diff --git a/website/source/intro/getting-started/parallel-builds.html.markdown b/website/source/intro/getting-started/parallel-builds.html.markdown index 2a5b422f8..e51311214 100644 --- a/website/source/intro/getting-started/parallel-builds.html.markdown +++ b/website/source/intro/getting-started/parallel-builds.html.markdown @@ -63,13 +63,23 @@ array.
 {
   "type": "digitalocean",
-  "api_key": "INSERT API KEY HERE",
-  "client_id": "INSERT CLIENT ID HERE"
+  "api_key": "{{user `do_api_key`}}",
+  "client_id": "{{user `do_client_id`}}"
 }
 
-Fill in your `api_key` and `client_id` for DigitalOcean as necessary. -The entire template should now [look like this](https://gist.github.com/mitchellh/51a447e38e7e496eb29c). +You'll also need to modify the `variables` section of the template +to include the access keys for DigitalOcean. + +
+"variables": {
+  ...
+  "do_api_key": "",
+  "do_client_id": ""
+}
+
+ +The entire template should now [look like this](https://gist.github.com/pearkes/cc5f8505eee5403a43a6). Additional builders are simply added to the `builders` array in the template. This tells Packer to build multiple images. The builder `type` values don't @@ -87,13 +97,18 @@ manual that contains a listing of all the available configuration options. ## Build -Now run `packer build example.json`. The output is too verbose to include +Now run `packer build` with your user variables. The output is too verbose to include all of it, but a portion of it is reproduced below. Note that the ordering and wording of the lines may be slightly different, but the effect is the same. ``` -$ packer build example.json +$ packer build \ + -var 'aws_access_key=YOUR ACCESS KEY' \ + -var 'aws_secret_key=YOUR SECRET KEY' \ + -var 'do_api_key=YOUR API KEY' \ + -var 'do_client_id=YOUR CLIENT ID' \ + example.json ==> amazon-ebs: amazon-ebs output will be in this color. ==> digitalocean: digitalocean output will be in this color. diff --git a/website/source/intro/getting-started/provision.html.markdown b/website/source/intro/getting-started/provision.html.markdown index fa6016744..4276ae089 100644 --- a/website/source/intro/getting-started/provision.html.markdown +++ b/website/source/intro/getting-started/provision.html.markdown @@ -37,6 +37,7 @@ block below.
 {
+  "variables": [...],
   "builders": [...],
 
   "provisioners": [{