This commit is contained in:
Anders Quist 2016-01-15 08:11:35 +01:00
commit 077f9621f2
117 changed files with 764 additions and 833 deletions

View File

@ -2,36 +2,63 @@
BACKWARDS INCOMPATIBILITIES:
* Packer now ships as a single binary, including plugins. If you install packer 0.9.0 over a previous packer installation, **you must delete all of the packer-* plugin files** or packer will load out-of-date plugins from disk.
* Packer now ships as a single binary, including plugins. If you install
packer 0.9.0 over a previous packer installation, **you must delete all of
the packer-* plugin files** or packer will load out-of-date plugins from
disk.
* Release binaries are now provided via <https://releases.hashicorp.com>.
* Packer 0.9.0 is now built with Go 1.5. Future versions will drop support for building with Go 1.4.
* Packer 0.9.0 is now built with Go 1.5. Future versions will drop support
for building with Go 1.4.
FEATURES:
* **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.
* **New `vmware-esxi` feature**: Packer can now export images from vCloud or vSphere during the build. [GH-1921]
processing. This allows you to extract artifacts from a packer builder and
use them with other post-processors like compress, docker, and Atlas.
* **New `vmware-esxi` feature**: Packer can now export images from vCloud or
vSphere during the build. [GH-1921]
IMPROVEMENTS:
* core: Packer plugins are now compiled into the main binary, reducing file size and build times, and making packer easier to install. The overall plugin architecture has not changed and third-party plugins can still be loaded from disk. Please make sure your plugins are up-to-date! [GH-2854]
* core: Packer plugins are now compiled into the main binary, reducing file
size and build times, and making packer easier to install. The overall
plugin architecture has not changed and third-party plugins can still be
loaded from disk. Please make sure your plugins are up-to-date! [GH-2854]
* core: Packer now indicates line numbers for template parse errors [GH-2742]
* core: Scripts are executed via `/usr/bin/env bash` instead of `/bin/bash` for broader compatibility. [GH-2913]
* core: Scripts are executed via `/usr/bin/env bash` instead of `/bin/bash`
for broader compatibility. [GH-2913]
* core: `target_path` for builder downloads can now be specified. [GH-2600]
* core: WinRM communicator now supports HTTPS protocol [GH-3061]
* builder/amazon: Add support for `ebs_optimized` [GH-2806]
* builder/amazon: You can now specify `0` for `spot_price` to switch to on demand instances [GH-2845]
* builder/google: `account_file` can now be provided as a JSON string [GH-2811]
* builder/amazon: You can now specify `0` for `spot_price` to switch to on
demand instances [GH-2845]
* builder/amazon: Added `ap-northeast-2` (Seoul) [GH-3056]
* builder/amazon: packer will try to derive the AZ if only a subnet is
specified [GH-3037]
* builder/digitalocean: doubled instance wait timeouts to power off or
shutdown (now 4 minutes) and to complete a snapshot (now 20 minutes)
[GH-2939]
* builder/google: `account_file` can now be provided as a JSON string
[GH-2811]
* builder/google: added support for `preemptible` instances [GH-2982]
* builder/google: added support for static external IPs via `address` option
[GH-3030]
* builder/openstack: added retry on WaitForImage 404 [GH-3009]
* builder/parallels: Improve support for Parallels 11 [GH-2662]
* builder/parallels: Parallels disks are now compacted by default [GH-2731]
* builder/parallels: Packer will look for Parallels in `/Applications/Parallels Desktop.app` if it is not detected automatically [GH-2839]
* builder/parallels: Packer will look for Parallels in
`/Applications/Parallels Desktop.app` if it is not detected automatically
[GH-2839]
* builder/docker: Now works remote hosts, such as boot2docker [GH-2846]
* builder/qemu: qcow2 images are now compacted by default [GH-2748]
* builder/qemu: qcow2 images can now be compressed [GH-2748]
* builder/qemu: Now specifies `virtio-scsi` by default [GH-2422]
* builder/qemu: Now checks for version-specific options [GH-2376]
* builder/docker-import: Can now import Artifice artifacts [GH-2718]
* builder/vmware-esxi: Now supports private key auth for remote builds via
`remote_private_key_file` [GH-2912]
* provisioner/chef: Now supports `encrypted_data_bag_secret_path` option
[GH-2653]
* provisioner/puppet: Now accepts the `extra_arguments` parameter [GH-2635]
* post-processor/atlas: Added support for compile ID. [GH-2775]
@ -44,6 +71,8 @@ BUG FIXES:
* builder/amazon: Use snapshot size when volume size is unspecified [GH-2480]
* builder/parallels: Now supports interpolation in `prlctl_post` [GH-2828]
* builder/vmware: `format` option is now read correctly [GH-2892]
* builder/vmware-esxi: Correct endless loop in destroy validation logic
[GH-2911]
* provisioner/shell: No longer leaves temp scripts behind [GH-1536]
* provisioner/winrm: Now waits for reboot to complete before continuing with provisioning [GH-2568]
* post-processor/artifice: Fix truncation of files downloaded from Docker. [GH-2793]

View File

@ -30,6 +30,11 @@ func TestAMIConfigPrepare_regions(t *testing.T) {
t.Fatalf("shouldn't have err: %s", err)
}
c.AMIRegions = listEC2Regions()
if err := c.Prepare(nil); err != nil {
t.Fatalf("shouldn't have err: %s", err)
}
c.AMIRegions = []string{"foo"}
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")

View File

@ -1,13 +1,26 @@
package common
// IsValidRegion returns true if the supplied region is a valid AWS
func listEC2Regions() []string {
return []string{
"ap-northeast-1",
"ap-northeast-2",
"ap-southeast-1",
"ap-southeast-2",
"cn-north-1",
"eu-central-1",
"eu-west-1",
"sa-east-1",
"us-east-1",
"us-gov-west-1",
"us-west-1",
"us-west-2",
}
}
// ValidateRegion returns true if the supplied region is a valid AWS
// region and false if it's not.
func ValidateRegion(region string) bool {
var regions = [11]string{"us-east-1", "us-west-2", "us-west-1", "eu-west-1",
"eu-central-1", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1",
"sa-east-1", "cn-north-1", "us-gov-west-1"}
for _, valid := range regions {
for _, valid := range listEC2Regions() {
if region == valid {
return true
}

View File

@ -72,6 +72,17 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
session := session.New(config)
ec2conn := ec2.New(session)
// If the subnet is specified but not the AZ, try to determine the AZ automatically
if b.config.SubnetId != "" && b.config.AvailabilityZone == "" {
log.Printf("[INFO] Finding AZ for the given subnet '%s'", b.config.SubnetId)
resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsInput{SubnetIds: []*string{&b.config.SubnetId}})
if err != nil {
return nil, err
}
b.config.AvailabilityZone = *resp.Subnets[0].AvailabilityZone
log.Printf("[INFO] AZ found: '%s'", b.config.AvailabilityZone)
}
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)
state.Put("config", b.config)

View File

@ -163,6 +163,17 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
session := session.New(config)
ec2conn := ec2.New(session)
// If the subnet is specified but not the AZ, try to determine the AZ automatically
if b.config.SubnetId != "" && b.config.AvailabilityZone == "" {
log.Printf("[INFO] Finding AZ for the given subnet '%s'", b.config.SubnetId)
resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsInput{SubnetIds: []*string{&b.config.SubnetId}})
if err != nil {
return nil, err
}
b.config.AvailabilityZone = *resp.Subnets[0].AvailabilityZone
log.Printf("[INFO] AZ found: '%s'", b.config.AvailabilityZone)
}
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)
state.Put("config", &b.config)

View File

@ -50,7 +50,7 @@ func (s *stepPowerOff) Run(state multistep.StateBag) multistep.StepAction {
}
// Wait for the droplet to become unlocked for future steps
if err := waitForDropletUnlocked(client, dropletId, 2*time.Minute); err != nil {
if err := waitForDropletUnlocked(client, dropletId, 4*time.Minute); err != nil {
// If we get an error the first time, actually report it
err := fmt.Errorf("Error powering off droplet: %s", err)
state.Put("error", err)

View File

@ -72,7 +72,7 @@ func (s *stepShutdown) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
if err := waitForDropletUnlocked(client, dropletId, 2*time.Minute); err != nil {
if err := waitForDropletUnlocked(client, dropletId, 4*time.Minute); err != nil {
// If we get an error the first time, actually report it
err := fmt.Errorf("Error shutting down droplet: %s", err)
state.Put("error", err)

View File

@ -30,8 +30,8 @@ func (s *stepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
// Wait for the droplet to become unlocked first. For snapshots
// this can end up taking quite a long time, so we hardcode this to
// 10 minutes.
if err := waitForDropletUnlocked(client, dropletId, 10*time.Minute); err != nil {
// 20 minutes.
if err := waitForDropletUnlocked(client, dropletId, 20*time.Minute); err != nil {
// If we get an error the first time, actually report it
err := fmt.Errorf("Error shutting down droplet: %s", err)
state.Put("error", err)

View File

@ -31,6 +31,7 @@ type Config struct {
MachineType string `mapstructure:"machine_type"`
Metadata map[string]string `mapstructure:"metadata"`
Network string `mapstructure:"network"`
Address string `mapstructure:"address"`
Preemptible bool `mapstructure:"preemptible"`
SourceImage string `mapstructure:"source_image"`
SourceImageProjectId string `mapstructure:"source_image_project_id"`

View File

@ -47,6 +47,7 @@ type InstanceConfig struct {
Metadata map[string]string
Name string
Network string
Address string
Preemptible bool
Tags []string
Zone string

View File

@ -13,6 +13,7 @@ import (
"golang.org/x/oauth2/google"
"golang.org/x/oauth2/jwt"
"google.golang.org/api/compute/v1"
"strings"
)
// driverGCE is a Driver implementation that actually talks to GCE.
@ -214,6 +215,23 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) {
return nil, err
}
// If given a regional ip, get it
accessconfig := compute.AccessConfig{
Name: "AccessConfig created by Packer",
Type: "ONE_TO_ONE_NAT",
}
if c.Address != "" {
d.ui.Message(fmt.Sprintf("Looking up address: %s", c.Address))
region_url := strings.Split(zone.Region, "/")
region := region_url[len(region_url)-1]
address, err := d.service.Addresses.Get(d.projectId, region, c.Address).Do()
if err != nil {
return nil, err
}
accessconfig.NatIP = address.Address
}
// Build up the metadata
metadata := make([]*compute.MetadataItems, len(c.Metadata))
for k, v := range c.Metadata {
@ -247,10 +265,7 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) {
NetworkInterfaces: []*compute.NetworkInterface{
&compute.NetworkInterface{
AccessConfigs: []*compute.AccessConfig{
&compute.AccessConfig{
Name: "AccessConfig created by Packer",
Type: "ONE_TO_ONE_NAT",
},
&accessconfig,
},
Network: network.SelfLink,
},

View File

@ -59,6 +59,7 @@ func (s *StepCreateInstance) Run(state multistep.StateBag) multistep.StepAction
Metadata: config.getInstanceMetadata(sshPublicKey),
Name: name,
Network: config.Network,
Address: config.Address,
Preemptible: config.Preemptible,
Tags: config.Tags,
Zone: config.Zone,

View File

@ -62,12 +62,20 @@ func (s *stepCreateImage) Cleanup(multistep.StateBag) {
// WaitForImage waits for the given Image ID to become ready.
func WaitForImage(client *gophercloud.ServiceClient, imageId string) error {
maxNumErrors := 10
numErrors := 0
for {
image, err := images.Get(client, imageId).Extract()
if err != nil {
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
if ok && errCode.Actual == 500 {
log.Printf("[ERROR] 500 error received, will ignore and retry: %s", err)
if ok && (errCode.Actual == 500 || errCode.Actual == 404) {
numErrors++
if numErrors >= maxNumErrors {
log.Printf("[ERROR] Maximum number of errors (%d) reached; failing with: %s", numErrors, err)
return err
}
log.Printf("[ERROR] %d error received, will ignore and retry: %s", errCode.Actual, err)
time.Sleep(2 * time.Second)
continue
}

View File

@ -23,6 +23,7 @@ type Builder struct {
type Config struct {
common.PackerConfig `mapstructure:",squash"`
common.HTTPConfig `mapstructure:",squash"`
common.ISOConfig `mapstructure:",squash"`
parallelscommon.FloppyConfig `mapstructure:",squash"`
parallelscommon.OutputConfig `mapstructure:",squash"`
@ -39,9 +40,6 @@ type Config struct {
GuestOSType string `mapstructure:"guest_os_type"`
HardDriveInterface string `mapstructure:"hard_drive_interface"`
HostInterfaces []string `mapstructure:"host_interfaces"`
HTTPDir string `mapstructure:"http_directory"`
HTTPPortMin uint `mapstructure:"http_port_min"`
HTTPPortMax uint `mapstructure:"http_port_max"`
SkipCompaction bool `mapstructure:"skip_compaction"`
VMName string `mapstructure:"vm_name"`
@ -77,6 +75,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
warnings = append(warnings, isoWarnings...)
errs = packer.MultiErrorAppend(errs, isoErrs...)
errs = packer.MultiErrorAppend(errs, b.config.HTTPConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(
errs, b.config.OutputConfig.Prepare(&b.config.ctx, &b.config.PackerConfig)...)
@ -110,14 +109,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
"Run it to see all available values: `prlctl create x -d list` ")
}
if b.config.HTTPPortMin == 0 {
b.config.HTTPPortMin = 8000
}
if b.config.HTTPPortMax == 0 {
b.config.HTTPPortMax = 9000
}
if len(b.config.HostInterfaces) == 0 {
b.config.HostInterfaces = []string{"en0", "en1", "en2", "en3", "en4", "en5", "en6", "en7",
"en8", "en9", "ppp0", "ppp1", "ppp2"}
@ -132,11 +123,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
errs, errors.New("hard_drive_interface can only be ide, sata, or scsi"))
}
if b.config.HTTPPortMin > b.config.HTTPPortMax {
errs = packer.MultiErrorAppend(
errs, errors.New("http_port_min must be less than http_port_max"))
}
// Warnings
if b.config.ShutdownCommand == "" {
warnings = append(warnings,
@ -185,7 +171,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&common.StepCreateFloppy{
Files: b.config.FloppyFiles,
},
new(stepHTTPServer),
&common.StepHTTPServer{
HTTPDir: b.config.HTTPDir,
HTTPPortMin: b.config.HTTPPortMin,
HTTPPortMax: b.config.HTTPPortMax,
},
new(stepCreateVM),
new(stepCreateDisk),
new(stepSetBootOrder),

View File

@ -138,45 +138,6 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) {
}
}
func TestBuilderPrepare_HTTPPort(t *testing.T) {
var b Builder
config := testConfig()
// Bad
config["http_port_min"] = 1000
config["http_port_max"] = 500
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Bad
config["http_port_min"] = -500
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Good
config["http_port_min"] = 500
config["http_port_max"] = 1000
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}
func TestBuilderPrepare_InvalidKey(t *testing.T) {
var b Builder
config := testConfig()

View File

@ -1,76 +0,0 @@
package iso
import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"math/rand"
"net"
"net/http"
)
// This step creates and runs the HTTP server that is serving files from the
// directory specified by the 'http_directory` configuration parameter in the
// template.
//
// Uses:
// config *config
// ui packer.Ui
//
// Produces:
// http_port int - The port the HTTP server started on.
type stepHTTPServer struct {
l net.Listener
}
func (s *stepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
var httpPort uint = 0
if config.HTTPDir == "" {
state.Put("http_port", httpPort)
return multistep.ActionContinue
}
// Find an available TCP port for our HTTP server
var httpAddr string
portRange := int(config.HTTPPortMax - config.HTTPPortMin)
for {
var err error
var offset uint = 0
if portRange > 0 {
// Intn will panic if portRange == 0, so we do a check.
offset = uint(rand.Intn(portRange))
}
httpPort = offset + config.HTTPPortMin
httpAddr = fmt.Sprintf(":%d", httpPort)
log.Printf("Trying port: %d", httpPort)
s.l, err = net.Listen("tcp", httpAddr)
if err == nil {
break
}
}
ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
// Start the HTTP server and run it in the background
fileServer := http.FileServer(http.Dir(config.HTTPDir))
server := &http.Server{Addr: httpAddr, Handler: fileServer}
go server.Serve(s.l)
// Save the address into the state so it can be accessed in the future
state.Put("http_port", httpPort)
return multistep.ActionContinue
}
func (s *stepHTTPServer) Cleanup(multistep.StateBag) {
if s.l != nil {
// Close the listener so that the HTTP server stops
s.l.Close()
}
}

View File

@ -79,6 +79,7 @@ type Builder struct {
type Config struct {
common.PackerConfig `mapstructure:",squash"`
common.HTTPConfig `mapstructure:",squash"`
common.ISOConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
@ -94,9 +95,6 @@ type Config struct {
Format string `mapstructure:"format"`
Headless bool `mapstructure:"headless"`
DiskImage bool `mapstructure:"disk_image"`
HTTPDir string `mapstructure:"http_directory"`
HTTPPortMin uint `mapstructure:"http_port_min"`
HTTPPortMax uint `mapstructure:"http_port_max"`
MachineType string `mapstructure:"machine_type"`
NetDevice string `mapstructure:"net_device"`
OutputDir string `mapstructure:"output_directory"`
@ -160,14 +158,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
}
}
if b.config.HTTPPortMin == 0 {
b.config.HTTPPortMin = 8000
}
if b.config.HTTPPortMax == 0 {
b.config.HTTPPortMax = 9000
}
if b.config.MachineType == "" {
b.config.MachineType = "pc"
}
@ -235,6 +225,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
warnings = append(warnings, isoWarnings...)
errs = packer.MultiErrorAppend(errs, isoErrs...)
errs = packer.MultiErrorAppend(errs, b.config.HTTPConfig.Prepare(&b.config.ctx)...)
if es := b.config.Comm.Prepare(&b.config.ctx); len(es) > 0 {
errs = packer.MultiErrorAppend(errs, es...)
}
@ -274,11 +265,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
errs, errors.New("unrecognized disk cache type"))
}
if b.config.HTTPPortMin > b.config.HTTPPortMax {
errs = packer.MultiErrorAppend(
errs, errors.New("http_port_min must be less than http_port_max"))
}
if !b.config.PackerForce {
if _, err := os.Stat(b.config.OutputDir); err == nil {
errs = packer.MultiErrorAppend(
@ -357,7 +343,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
new(stepCreateDisk),
new(stepCopyDisk),
new(stepResizeDisk),
new(stepHTTPServer),
&common.StepHTTPServer{
HTTPDir: b.config.HTTPDir,
HTTPPortMin: b.config.HTTPPortMin,
HTTPPortMax: b.config.HTTPPortMax,
},
new(stepForwardSSH),
new(stepConfigureVNC),
steprun,

View File

@ -206,45 +206,6 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
}
}
func TestBuilderPrepare_HTTPPort(t *testing.T) {
var b Builder
config := testConfig()
// Bad
config["http_port_min"] = 1000
config["http_port_max"] = 500
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Bad
config["http_port_min"] = -500
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Good
config["http_port_min"] = 500
config["http_port_max"] = 1000
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}
func TestBuilderPrepare_Format(t *testing.T) {
var b Builder
config := testConfig()

View File

@ -1,76 +0,0 @@
package qemu
import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"math/rand"
"net"
"net/http"
)
// This step creates and runs the HTTP server that is serving files from the
// directory specified by the 'http_directory` configuration parameter in the
// template.
//
// Uses:
// config *config
// ui packer.Ui
//
// Produces:
// http_port int - The port the HTTP server started on.
type stepHTTPServer struct {
l net.Listener
}
func (s *stepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
var httpPort uint = 0
if config.HTTPDir == "" {
state.Put("http_port", httpPort)
return multistep.ActionContinue
}
// Find an available TCP port for our HTTP server
var httpAddr string
portRange := int(config.HTTPPortMax - config.HTTPPortMin)
for {
var err error
var offset uint = 0
if portRange > 0 {
// Intn will panic if portRange == 0, so we do a check.
offset = uint(rand.Intn(portRange))
}
httpPort = offset + config.HTTPPortMin
httpAddr = fmt.Sprintf(":%d", httpPort)
log.Printf("Trying port: %d", httpPort)
s.l, err = net.Listen("tcp", httpAddr)
if err == nil {
break
}
}
ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
// Start the HTTP server and run it in the background
fileServer := http.FileServer(http.Dir(config.HTTPDir))
server := &http.Server{Addr: httpAddr, Handler: fileServer}
go server.Serve(s.l)
// Save the address into the state so it can be accessed in the future
state.Put("http_port", httpPort)
return multistep.ActionContinue
}
func (s *stepHTTPServer) Cleanup(multistep.StateBag) {
if s.l != nil {
// Close the listener so that the HTTP server stops
s.l.Close()
}
}

View File

@ -1,7 +1,6 @@
package common
import (
"errors"
"fmt"
"time"
@ -12,10 +11,6 @@ type RunConfig struct {
Headless bool `mapstructure:"headless"`
RawBootWait string `mapstructure:"boot_wait"`
HTTPDir string `mapstructure:"http_directory"`
HTTPPortMin uint `mapstructure:"http_port_min"`
HTTPPortMax uint `mapstructure:"http_port_max"`
BootWait time.Duration ``
}
@ -24,14 +19,6 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
c.RawBootWait = "10s"
}
if c.HTTPPortMin == 0 {
c.HTTPPortMin = 8000
}
if c.HTTPPortMax == 0 {
c.HTTPPortMax = 9000
}
var errs []error
var err error
c.BootWait, err = time.ParseDuration(c.RawBootWait)
@ -39,10 +26,5 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
errs = append(errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
}
if c.HTTPPortMin > c.HTTPPortMax {
errs = append(errs,
errors.New("http_port_min must be less than http_port_max"))
}
return errs
}

View File

@ -24,6 +24,7 @@ type Builder struct {
type Config struct {
common.PackerConfig `mapstructure:",squash"`
common.HTTPConfig `mapstructure:",squash"`
common.ISOConfig `mapstructure:",squash"`
vboxcommon.ExportConfig `mapstructure:",squash"`
vboxcommon.ExportOpts `mapstructure:",squash"`
@ -81,6 +82,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(
errs, b.config.OutputConfig.Prepare(&b.config.ctx, &b.config.PackerConfig)...)
errs = packer.MultiErrorAppend(errs, b.config.HTTPConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(&b.config.ctx)...)
@ -194,7 +196,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&common.StepCreateFloppy{
Files: b.config.FloppyFiles,
},
&vboxcommon.StepHTTPServer{
&common.StepHTTPServer{
HTTPDir: b.config.HTTPDir,
HTTPPortMin: b.config.HTTPPortMin,
HTTPPortMax: b.config.HTTPPortMax,

View File

@ -260,45 +260,6 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) {
}
}
func TestBuilderPrepare_HTTPPort(t *testing.T) {
var b Builder
config := testConfig()
// Bad
config["http_port_min"] = 1000
config["http_port_max"] = 500
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Bad
config["http_port_min"] = -500
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Good
config["http_port_min"] = 500
config["http_port_max"] = 1000
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}
func TestBuilderPrepare_InvalidKey(t *testing.T) {
var b Builder
config := testConfig()

View File

@ -1,76 +0,0 @@
package iso
import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"math/rand"
"net"
"net/http"
)
// This step creates and runs the HTTP server that is serving files from the
// directory specified by the 'http_directory` configuration parameter in the
// template.
//
// Uses:
// config *config
// ui packer.Ui
//
// Produces:
// http_port int - The port the HTTP server started on.
type stepHTTPServer struct {
l net.Listener
}
func (s *stepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
var httpPort uint = 0
if config.HTTPDir == "" {
state.Put("http_port", httpPort)
return multistep.ActionContinue
}
// Find an available TCP port for our HTTP server
var httpAddr string
portRange := int(config.HTTPPortMax - config.HTTPPortMin)
for {
var err error
var offset uint = 0
if portRange > 0 {
// Intn will panic if portRange == 0, so we do a check.
offset = uint(rand.Intn(portRange))
}
httpPort = offset + config.HTTPPortMin
httpAddr = fmt.Sprintf(":%d", httpPort)
log.Printf("Trying port: %d", httpPort)
s.l, err = net.Listen("tcp", httpAddr)
if err == nil {
break
}
}
ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
// Start the HTTP server and run it in the background
fileServer := http.FileServer(http.Dir(config.HTTPDir))
server := &http.Server{Addr: httpAddr, Handler: fileServer}
go server.Serve(s.l)
// Save the address into the state so it can be accessed in the future
state.Put("http_port", httpPort)
return multistep.ActionContinue
}
func (s *stepHTTPServer) Cleanup(multistep.StateBag) {
if s.l != nil {
// Close the listener so that the HTTP server stops
s.l.Close()
}
}

View File

@ -57,7 +57,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&common.StepCreateFloppy{
Files: b.config.FloppyFiles,
},
&vboxcommon.StepHTTPServer{
&common.StepHTTPServer{
HTTPDir: b.config.HTTPDir,
HTTPPortMin: b.config.HTTPPortMin,
HTTPPortMax: b.config.HTTPPortMax,

View File

@ -15,6 +15,7 @@ import (
// Config is the configuration structure for the builder.
type Config struct {
common.PackerConfig `mapstructure:",squash"`
common.HTTPConfig `mapstructure:",squash"`
vboxcommon.ExportConfig `mapstructure:",squash"`
vboxcommon.ExportOpts `mapstructure:",squash"`
vboxcommon.FloppyConfig `mapstructure:",squash"`
@ -77,6 +78,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, c.ExportConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.ExportOpts.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(&c.ctx, &c.PackerConfig)...)
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(&c.ctx)...)

View File

@ -1,7 +1,6 @@
package common
import (
"errors"
"fmt"
"time"
@ -12,10 +11,6 @@ type RunConfig struct {
Headless bool `mapstructure:"headless"`
RawBootWait string `mapstructure:"boot_wait"`
HTTPDir string `mapstructure:"http_directory"`
HTTPPortMin uint `mapstructure:"http_port_min"`
HTTPPortMax uint `mapstructure:"http_port_max"`
VNCPortMin uint `mapstructure:"vnc_port_min"`
VNCPortMax uint `mapstructure:"vnc_port_max"`
@ -27,14 +22,6 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
c.RawBootWait = "10s"
}
if c.HTTPPortMin == 0 {
c.HTTPPortMin = 8000
}
if c.HTTPPortMax == 0 {
c.HTTPPortMax = 9000
}
if c.VNCPortMin == 0 {
c.VNCPortMin = 5900
}
@ -53,11 +40,6 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
}
}
if c.HTTPPortMin > c.HTTPPortMax {
errs = append(errs,
errors.New("http_port_min must be less than http_port_max"))
}
if c.VNCPortMin > c.VNCPortMax {
errs = append(
errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max"))

View File

@ -1,78 +0,0 @@
package common
import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"math/rand"
"net"
"net/http"
)
// This step creates and runs the HTTP server that is serving files from the
// directory specified by the 'http_directory` configuration parameter in the
// template.
//
// Uses:
// ui packer.Ui
//
// Produces:
// http_port int - The port the HTTP server started on.
type StepHTTPServer struct {
HTTPDir string
HTTPPortMin uint
HTTPPortMax uint
l net.Listener
}
func (s *StepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
var httpPort uint = 0
if s.HTTPDir == "" {
state.Put("http_port", httpPort)
return multistep.ActionContinue
}
// Find an available TCP port for our HTTP server
var httpAddr string
portRange := int(s.HTTPPortMax - s.HTTPPortMin)
for {
var err error
var offset uint = 0
if portRange > 0 {
// Intn will panic if portRange == 0, so we do a check.
offset = uint(rand.Intn(portRange))
}
httpPort = offset + s.HTTPPortMin
httpAddr = fmt.Sprintf("0.0.0.0:%d", httpPort)
log.Printf("Trying port: %d", httpPort)
s.l, err = net.Listen("tcp", httpAddr)
if err == nil {
break
}
}
ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
// Start the HTTP server and run it in the background
fileServer := http.FileServer(http.Dir(s.HTTPDir))
server := &http.Server{Addr: httpAddr, Handler: fileServer}
go server.Serve(s.l)
// Save the address into the state so it can be accessed in the future
state.Put("http_port", httpPort)
return multistep.ActionContinue
}
func (s *StepHTTPServer) Cleanup(multistep.StateBag) {
if s.l != nil {
// Close the listener so that the HTTP server stops
s.l.Close()
}
}

View File

@ -26,6 +26,7 @@ type Builder struct {
type Config struct {
common.PackerConfig `mapstructure:",squash"`
common.HTTPConfig `mapstructure:",squash"`
common.ISOConfig `mapstructure:",squash"`
vmwcommon.DriverConfig `mapstructure:",squash"`
vmwcommon.OutputConfig `mapstructure:",squash"`
@ -57,6 +58,7 @@ type Config struct {
RemotePort uint `mapstructure:"remote_port"`
RemoteUser string `mapstructure:"remote_username"`
RemotePassword string `mapstructure:"remote_password"`
RemotePrivateKey string `mapstructure:"remote_private_key_file"`
ctx interpolate.Context
}
@ -83,6 +85,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
isoWarnings, isoErrs := b.config.ISOConfig.Prepare(&b.config.ctx)
warnings = append(warnings, isoWarnings...)
errs = packer.MultiErrorAppend(errs, isoErrs...)
errs = packer.MultiErrorAppend(errs, b.config.HTTPConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.DriverConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs,
b.config.OutputConfig.Prepare(&b.config.ctx, &b.config.PackerConfig)...)
@ -244,7 +247,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
CustomData: b.config.VMXData,
},
&vmwcommon.StepSuppressMessages{},
&vmwcommon.StepHTTPServer{
&common.StepHTTPServer{
HTTPDir: b.config.HTTPDir,
HTTPPortMin: b.config.HTTPPortMin,
HTTPPortMax: b.config.HTTPPortMax,

View File

@ -152,45 +152,6 @@ func TestBuilderPrepare_Format(t *testing.T) {
}
}
func TestBuilderPrepare_HTTPPort(t *testing.T) {
var b Builder
config := testConfig()
// Bad
config["http_port_min"] = 1000
config["http_port_max"] = 500
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Bad
config["http_port_min"] = -500
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Good
config["http_port_min"] = 500
config["http_port_max"] = 1000
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}
func TestBuilderPrepare_InvalidKey(t *testing.T) {
var b Builder
config := testConfig()

View File

@ -21,6 +21,7 @@ func NewDriver(config *Config) (vmwcommon.Driver, error) {
Port: config.RemotePort,
Username: config.RemoteUser,
Password: config.RemotePassword,
PrivateKey: config.RemotePrivateKey,
Datastore: config.RemoteDatastore,
CacheDatastore: config.RemoteCacheDatastore,
CacheDirectory: config.RemoteCacheDirectory,

View File

@ -15,6 +15,7 @@ import (
"time"
"github.com/mitchellh/multistep"
commonssh "github.com/mitchellh/packer/common/ssh"
"github.com/mitchellh/packer/communicator/ssh"
"github.com/mitchellh/packer/packer"
gossh "golang.org/x/crypto/ssh"
@ -27,6 +28,7 @@ type ESX5Driver struct {
Port uint
Username string
Password string
PrivateKey string
Datastore string
CacheDatastore string
CacheDirectory string
@ -340,7 +342,15 @@ func (d *ESX5Driver) connect() error {
ssh.PasswordKeyboardInteractive(d.Password)),
}
// TODO(dougm) KeyPath support
if d.PrivateKey != "" {
signer, err := commonssh.FileSigner(d.PrivateKey)
if err != nil {
return err
}
auth = append(auth, gossh.PublicKeys(signer))
}
sshConfig := &ssh.Config{
Connection: ssh.ConnectFunc("tcp", address),
SSHConfig: &gossh.ClientConfig{

View File

@ -57,8 +57,8 @@ func (s *StepRegister) Cleanup(state multistep.StateBag) {
}
// Wait for the machine to actually destroy
for {
exists, _ := remoteDriver.IsDestroyed()
if !exists {
destroyed, _ := remoteDriver.IsDestroyed()
if destroyed {
break
}
time.Sleep(150 * time.Millisecond)

View File

@ -72,7 +72,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
CustomData: b.config.VMXData,
},
&vmwcommon.StepSuppressMessages{},
&vmwcommon.StepHTTPServer{
&common.StepHTTPServer{
HTTPDir: b.config.HTTPDir,
HTTPPortMin: b.config.HTTPPortMin,
HTTPPortMax: b.config.HTTPPortMax,

View File

@ -14,6 +14,7 @@ import (
// Config is the configuration structure for the builder.
type Config struct {
common.PackerConfig `mapstructure:",squash"`
common.HTTPConfig `mapstructure:",squash"`
vmwcommon.DriverConfig `mapstructure:",squash"`
vmwcommon.OutputConfig `mapstructure:",squash"`
vmwcommon.RunConfig `mapstructure:",squash"`
@ -56,6 +57,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
// Prepare the errors
var errs *packer.MultiError
errs = packer.MultiErrorAppend(errs, c.DriverConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(&c.ctx, &c.PackerConfig)...)
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(&c.ctx)...)

View File

@ -53,6 +53,10 @@ func (c *PushCommand) Run(args []string) int {
return 1
}
if message != "" {
c.Ui.Warn("[DEPRECATED] -m/-message is deprecated and will be removed in a future Packer release")
}
args = f.Args()
if len(args) != 1 {
f.Usage()
@ -268,9 +272,6 @@ Usage: packer push [options] TEMPLATE
Options:
-m, -message=<detail> A message to identify the purpose or changes in this
Packer template much like a VCS commit message
-name=<name> The destination build in Atlas. This is in a format
"username/name".

34
common/http_config.go Normal file
View File

@ -0,0 +1,34 @@
package common
import (
"errors"
"github.com/mitchellh/packer/template/interpolate"
)
// HTTPConfig contains configuration for the local HTTP Server
type HTTPConfig struct {
HTTPDir string `mapstructure:"http_directory"`
HTTPPortMin uint `mapstructure:"http_port_min"`
HTTPPortMax uint `mapstructure:"http_port_max"`
}
func (c *HTTPConfig) Prepare(ctx *interpolate.Context) []error {
// Validation
var errs []error
if c.HTTPPortMin == 0 {
c.HTTPPortMin = 8000
}
if c.HTTPPortMax == 0 {
c.HTTPPortMax = 9000
}
if c.HTTPPortMin > c.HTTPPortMax {
errs = append(errs,
errors.New("http_port_min must be less than http_port_max"))
}
return errs
}

View File

@ -0,0 +1,45 @@
package common
import (
"testing"
)
func TestHTTPConfigPrepare_Bounds(t *testing.T) {
// Test bad
h := HTTPConfig{
HTTPPortMin: 1000,
HTTPPortMax: 500,
}
err := h.Prepare(nil)
if err == nil {
t.Fatal("should have error")
}
// Test good
h = HTTPConfig{
HTTPPortMin: 0,
HTTPPortMax: 0,
}
err = h.Prepare(nil)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
portMin := uint(8000)
if h.HTTPPortMin != portMin {
t.Fatalf("HTTPPortMin: expected %d got %d", portMin, h.HTTPPortMin)
}
portMax := uint(9000)
if h.HTTPPortMax != portMax {
t.Fatalf("HTTPPortMax: expected %d got %d", portMax, h.HTTPPortMax)
}
// Test good
h = HTTPConfig{
HTTPPortMin: 500,
HTTPPortMax: 1000,
}
err = h.Prepare(nil)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}

View File

@ -28,6 +28,8 @@ func New(config *Config) (*Communicator, error) {
endpoint := &winrm.Endpoint{
Host: config.Host,
Port: config.Port,
HTTPS: config.Https,
Insecure: config.Insecure,
/*
TODO
@ -145,6 +147,8 @@ func (c *Communicator) newCopyClient() (*winrmcp.Winrmcp, error) {
User: c.config.Username,
Password: c.config.Password,
},
Https: c.config.Https,
Insecure: c.config.Insecure,
OperationTimeout: c.config.Timeout,
MaxOperationsPerShell: 15, // lowest common denominator
})

View File

@ -11,4 +11,6 @@ type Config struct {
Username string
Password string
Timeout time.Duration
Https bool
Insecure bool
}

View File

@ -36,6 +36,8 @@ type Config struct {
WinRMHost string `mapstructure:"winrm_host"`
WinRMPort int `mapstructure:"winrm_port"`
WinRMTimeout time.Duration `mapstructure:"winrm_timeout"`
WinRMUseSSL bool `mapstructure:"winrm_use_ssl"`
WinRMInsecure bool `mapstructure:"winrm_insecure"`
}
// Port returns the port that will be used for access based on config.

View File

@ -129,6 +129,8 @@ func (s *StepConnectWinRM) waitForWinRM(state multistep.StateBag, cancel <-chan
Username: user,
Password: password,
Timeout: s.Config.WinRMTimeout,
Https: s.Config.WinRMUseSSL,
Insecure: s.Config.WinRMInsecure,
})
if err != nil {
log.Printf("[ERROR] WinRM connection err: %s", err)

View File

@ -23,6 +23,7 @@ type Config struct {
common.PackerConfig `mapstructure:",squash"`
ChefEnvironment string `mapstructure:"chef_environment"`
EncryptedDataBagSecretPath string `mapstructure:"encrypted_data_bag_secret_path"`
SslVerifyMode string `mapstructure:"ssl_verify_mode"`
ConfigTemplate string `mapstructure:"config_template"`
ExecuteCommand string `mapstructure:"execute_command"`
@ -53,8 +54,10 @@ type ConfigTemplate struct {
ClientKey string
ValidationKeyPath string
ValidationClientName string
EncryptedDataBagSecretPath string
ChefEnvironment string
SslVerifyMode string
HasEncryptedDataBagSecretPath bool
}
type ExecuteTemplate struct {
@ -118,6 +121,15 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
errs, fmt.Errorf("server_url must be set"))
}
if p.config.EncryptedDataBagSecretPath != "" {
pFileInfo, err := os.Stat(p.config.EncryptedDataBagSecretPath)
if err != nil || pFileInfo.IsDir() {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Bad encrypted data bag secret '%s': %s", p.config.EncryptedDataBagSecretPath, err))
}
}
jsonValid := true
for k, v := range p.config.Json {
p.config.Json[k], err = p.deepJsonFix(k, v)
@ -175,8 +187,16 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
}
}
encryptedDataBagSecretPath := ""
if p.config.EncryptedDataBagSecretPath != "" {
encryptedDataBagSecretPath = fmt.Sprintf("%s/encrypted_data_bag_secret", p.config.StagingDir)
if err := p.uploadFile(ui, comm, encryptedDataBagSecretPath, p.config.EncryptedDataBagSecretPath); err != nil {
return fmt.Errorf("Error uploading encrypted data bag secret: %s", err)
}
}
configPath, err := p.createConfig(
ui, comm, nodeName, serverUrl, p.config.ClientKey, remoteValidationKeyPath, p.config.ValidationClientName, p.config.ChefEnvironment, p.config.SslVerifyMode)
ui, comm, nodeName, serverUrl, p.config.ClientKey, remoteValidationKeyPath, p.config.ValidationClientName, encryptedDataBagSecretPath, p.config.ChefEnvironment, p.config.SslVerifyMode)
if err != nil {
return fmt.Errorf("Error creating Chef config file: %s", err)
}
@ -236,7 +256,17 @@ func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, ds
return comm.UploadDir(dst, src, nil)
}
func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, clientKey string, remoteKeyPath string, validationClientName string, chefEnvironment string, sslVerifyMode string) (string, error) {
func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, dst string, src string) error {
f, err := os.Open(src)
if err != nil {
return err
}
defer f.Close()
return comm.Upload(dst, f, nil)
}
func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, clientKey string, remoteKeyPath string, validationClientName string, encryptedDataBagSecretPath string, chefEnvironment string, sslVerifyMode string) (string, error) {
ui.Message("Creating configuration file 'client.rb'")
// Read the template
@ -265,6 +295,8 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeN
ValidationClientName: validationClientName,
ChefEnvironment: chefEnvironment,
SslVerifyMode: sslVerifyMode,
EncryptedDataBagSecretPath: encryptedDataBagSecretPath,
HasEncryptedDataBagSecretPath: encryptedDataBagSecretPath != "",
}
configString, err := interpolate.Render(tpl, &ctx)
if err != nil {
@ -587,6 +619,9 @@ log_level :info
log_location STDOUT
chef_server_url "{{.ServerUrl}}"
client_key "{{.ClientKey}}"
{{if .HasEncryptedDataBagSecretPath}}
encrypted_data_bag_secret "{{.EncryptedDataBagSecretPath}}"
{{end}}
{{if ne .ValidationClientName ""}}
validation_client_name "{{.ValidationClientName}}"
{{else}}

View File

@ -138,6 +138,49 @@ func TestProvisionerPrepare_serverUrl(t *testing.T) {
}
}
func TestProvisionerPrepare_encryptedDataBagSecretPath(t *testing.T) {
var err error
var p Provisioner
// Test no config template
config := testConfig()
delete(config, "encrypted_data_bag_secret_path")
err = p.Prepare(config)
if err != nil {
t.Fatalf("err: %s", err)
}
// Test with a file
tf, err := ioutil.TempFile("", "packer")
if err != nil {
t.Fatalf("err: %s", err)
}
defer os.Remove(tf.Name())
config = testConfig()
config["encrypted_data_bag_secret_path"] = tf.Name()
p = Provisioner{}
err = p.Prepare(config)
if err != nil {
t.Fatalf("err: %s", err)
}
// Test with a directory
td, err := ioutil.TempDir("", "packer")
if err != nil {
t.Fatalf("err: %s", err)
}
defer os.RemoveAll(td)
config = testConfig()
config["encrypted_data_bag_secret_path"] = td
p = Provisioner{}
err = p.Prepare(config)
if err == nil {
t.Fatal("should have err")
}
}
func TestProvisioner_createDir(t *testing.T) {
p1 := &Provisioner{config: Config{PreventSudo: true}}
p2 := &Provisioner{config: Config{PreventSudo: false}}

View File

@ -1,33 +0,0 @@
#!/usr/bin/env bash
set -e
# Get the parent directory of where this script is.
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )"
# Change into that dir because we expect that
cd $DIR
# Get the version from the command line
VERSION=$1
if [ -z $VERSION ]; then
echo "Please specify a version."
exit 1
fi
# Make sure we have a bintray API key
if [ -z $BINTRAY_API_KEY ]; then
echo "Please set your bintray API key in the BINTRAY_API_KEY env var."
exit 1
fi
for ARCHIVE in ./pkg/dist/*; do
ARCHIVE_NAME=$(basename ${ARCHIVE})
echo Uploading: $ARCHIVE_NAME
curl \
-T ${ARCHIVE} \
-umitchellh:${BINTRAY_API_KEY} \
"https://api.bintray.com/content/mitchellh/packer/packer/${VERSION}/${ARCHIVE_NAME}"
done

View File

@ -1,40 +0,0 @@
#!/usr/bin/env bash
# Set the tmpdir
if [ -z "$TMPDIR" ]; then
TMPDIR="/tmp"
fi
# Create a temporary build dir and make sure we clean it up. For
# debugging, comment out the trap line.
DEPLOY=`mktemp -d $TMPDIR/packer-www-XXXXXX`
trap "rm -rf $DEPLOY" INT TERM EXIT
# Get the parent directory of where this script is.
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )"
# Copy into tmpdir
shopt -s dotglob
cp -r $DIR/website/* $DEPLOY/
# Change into that directory
pushd $DEPLOY &>/dev/null
# Ignore some stuff
touch .gitignore
echo ".sass-cache" >> .gitignore
echo "build" >> .gitignore
echo "vendor" >> .gitignore
# Add everything
git init -q .
git add .
git commit -q -m "Deploy by $USER"
git remote add heroku git@heroku.com:packer-www.git
git push -f heroku master
# Go back to our root
popd &>/dev/null

View File

@ -1,2 +0,0 @@
https://github.com/heroku/heroku-buildpack-ruby.git
https://github.com/hashicorp/heroku-buildpack-middleman.git

View File

@ -1 +0,0 @@
2.2.2

View File

@ -1,7 +1,5 @@
source "https://rubygems.org"
ruby "2.2.2"
gem "middleman-hashicorp", github: "hashicorp/middleman-hashicorp"
gem "middleman-breadcrumbs"
gem "htmlbeautifier"

View File

@ -1,6 +1,6 @@
GIT
remote: git://github.com/hashicorp/middleman-hashicorp.git
revision: 15cbda0cf1d963fa71292dee921229e7ee618272
revision: 953baf8762b915cf57553bcc82bc946ad777056f
specs:
middleman-hashicorp (0.2.0)
bootstrap-sass (~> 3.3)
@ -21,18 +21,18 @@ GIT
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.4)
activesupport (4.2.5)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
autoprefixer-rails (6.0.3)
autoprefixer-rails (6.2.3)
execjs
json
bootstrap-sass (3.3.5.1)
autoprefixer-rails (>= 5.0.0.1)
sass (>= 3.3.0)
bootstrap-sass (3.3.6)
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
builder (3.2.2)
capybara (2.4.4)
mime-types (>= 1.16)
@ -40,11 +40,11 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
chunky_png (1.3.4)
chunky_png (1.3.5)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.9.1.1)
coffee-script-source (1.10.0)
commonjs (0.2.7)
compass (1.0.3)
chunky_png (~> 1.2)
@ -63,7 +63,7 @@ GEM
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
erubis (2.7.0)
eventmachine (1.0.8)
eventmachine (1.0.9)
execjs (2.6.0)
ffi (1.9.10)
git-version-bump (0.15.1)
@ -81,23 +81,23 @@ GEM
less (2.6.0)
commonjs (~> 0.2.7)
libv8 (3.16.14.13)
listen (3.0.3)
listen (3.0.5)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
middleman (3.4.0)
middleman (3.4.1)
coffee-script (~> 2.2)
compass (>= 1.0.0, < 2.0.0)
compass-import-once (= 1.0.5)
execjs (~> 2.0)
haml (>= 4.0.5)
kramdown (~> 1.2)
middleman-core (= 3.4.0)
middleman-core (= 3.4.1)
middleman-sprockets (>= 3.1.2)
sass (>= 3.4.0, < 4.0)
uglifier (~> 2.5)
middleman-breadcrumbs (0.2.0)
middleman (>= 3.3.5)
middleman-core (3.4.0)
middleman-core (3.4.1)
activesupport (~> 4.1)
bundler (~> 1.1)
capybara (~> 2.4.4)
@ -109,7 +109,7 @@ GEM
rack (>= 1.4.5, < 2.0)
thor (>= 0.15.2, < 2.0)
tilt (~> 1.4.1, < 2.0)
middleman-livereload (3.4.3)
middleman-livereload (3.4.6)
em-websocket (~> 0.5.1)
middleman-core (>= 3.3)
rack-livereload (~> 0.3.15)
@ -121,15 +121,17 @@ GEM
sprockets (~> 2.12.1)
sprockets-helpers (~> 1.1.0)
sprockets-sass (~> 1.3.0)
middleman-syntax (2.0.0)
middleman-core (~> 3.2)
middleman-syntax (2.1.0)
middleman-core (>= 3.2)
rouge (~> 1.0)
mime-types (2.6.2)
mini_portile (0.6.2)
minitest (5.8.1)
mime-types (3.0)
mime-types-data (~> 3.2015)
mime-types-data (3.2015.1120)
mini_portile2 (2.0.0)
minitest (5.8.3)
multi_json (1.11.2)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
nokogiri (1.6.7.1)
mini_portile2 (~> 2.0.0.rc2)
padrino-helpers (0.12.5)
i18n (~> 0.6, >= 0.6.7)
padrino-support (= 0.12.5)
@ -148,13 +150,13 @@ GEM
rack-ssl-enforcer (0.2.9)
rack-test (0.6.3)
rack (>= 1.0)
rb-fsevent (0.9.6)
rb-fsevent (0.9.7)
rb-inotify (0.9.5)
ffi (>= 0.5.0)
redcarpet (3.3.3)
redcarpet (3.3.4)
ref (2.0.0)
rouge (1.10.1)
sass (3.4.19)
sass (3.4.21)
sprockets (2.12.4)
hike (~> 1.2)
multi_json (~> 1.0)

View File

@ -1 +0,0 @@
web: bundle exec thin start -p $PORT

12
website/Vagrantfile vendored
View File

@ -5,22 +5,22 @@ $script = <<SCRIPT
sudo apt-get -y update
# RVM/Ruby
sudo apt-get -y install curl
sudo apt-get -y install git
sudo apt-get -qy install curl git libgmp3-dev
gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
# Install rvm and the latest version of ruby
curl -sSL https://get.rvm.io | bash -s stable
. ~/.bashrc
. ~/.bash_profile
rvm install 2.0.0
rvm --default use 2.0.0
rvm install ruby-2.2.2
gem install bundler
# Middleman deps
cd /vagrant
bundle
make dev
SCRIPT
Vagrant.configure(2) do |config|
config.vm.box = "chef/ubuntu-12.04"
config.vm.box = "bento/ubuntu-14.04"
config.vm.network "private_network", ip: "33.33.30.10"
config.vm.provision "shell", inline: $script, privileged: false
config.vm.synced_folder ".", "/vagrant", type: "rsync"

41
website/packer.json Normal file
View File

@ -0,0 +1,41 @@
{
"variables": {
"aws_access_key_id": "{{ env `AWS_ACCESS_KEY_ID` }}",
"aws_secret_access_key": "{{ env `AWS_SECRET_ACCESS_KEY` }}",
"aws_region": "{{ env `AWS_REGION` }}",
"fastly_api_key": "{{ env `FASTLY_API_KEY` }}"
},
"builders": [
{
"type": "docker",
"image": "ruby:2.3-slim",
"commit": "true"
}
],
"provisioners": [
{
"type": "file",
"source": ".",
"destination": "/app"
},
{
"type": "shell",
"environment_vars": [
"AWS_ACCESS_KEY_ID={{ user `aws_access_key_id` }}",
"AWS_SECRET_ACCESS_KEY={{ user `aws_secret_access_key` }}",
"AWS_REGION={{ user `aws_region` }}",
"FASTLY_API_KEY={{ user `fastly_api_key` }}"
],
"inline": [
"apt-get update",
"apt-get install -y build-essential curl git libffi-dev s3cmd wget",
"cd /app",
"bundle check || bundle install --jobs 7",
"bundle exec middleman build",
"/bin/bash ./scripts/deploy.sh"
]
}
]
}

88
website/scripts/deploy.sh Executable file
View File

@ -0,0 +1,88 @@
#!/bin/bash
set -e
PROJECT="packer"
PROJECT_URL="www.packer.io"
FASTLY_SERVICE_ID="7GrxRJP3PVBuqQbyxYQ0MV"
# Ensure the proper AWS environment variables are set
if [ -z "$AWS_ACCESS_KEY_ID" ]; then
echo "Missing AWS_ACCESS_KEY_ID!"
exit 1
fi
if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
echo "Missing AWS_SECRET_ACCESS_KEY!"
exit 1
fi
# Ensure the proper Fastly keys are set
if [ -z "$FASTLY_API_KEY" ]; then
echo "Missing FASTLY_API_KEY!"
exit 1
fi
# Ensure we have s3cmd installed
if ! command -v "s3cmd" >/dev/null 2>&1; then
echo "Missing s3cmd!"
exit 1
fi
# Get the parent directory of where this script is and change into our website
# directory
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
DIR="$(cd -P "$( dirname "$SOURCE" )/.." && pwd)"
# Delete any .DS_Store files for our OS X friends.
find "$DIR" -type f -name '.DS_Store' -delete
# Upload the files to S3 - we disable mime-type detection by the python library
# and just guess from the file extension because it's surprisingly more
# accurate, especially for CSS and javascript. We also tag the uploaded files
# with the proper Surrogate-Key, which we will later purge in our API call to
# Fastly.
if [ -z "$NO_UPLOAD" ]; then
echo "Uploading to S3..."
# Check that the site has been built
if [ ! -d "$DIR/build" ]; then
echo "Missing compiled website! Run 'make build' to compile!"
exit 1
fi
s3cmd \
--quiet \
--delete-removed \
--guess-mime-type \
--no-mime-magic \
--acl-public \
--recursive \
--add-header="Cache-Control: max-age=31536000" \
--add-header="x-amz-meta-surrogate-key: site-$PROJECT" \
sync "$DIR/build/" "s3://hc-sites/$PROJECT/latest/"
fi
# Perform a soft-purge of the surrogate key.
if [ -z "$NO_PURGE" ]; then
echo "Purging Fastly cache..."
curl \
--fail \
--silent \
--output /dev/null \
--request "POST" \
--header "Accept: application/json" \
--header "Fastly-Key: $FASTLY_API_KEY" \
--header "Fastly-Soft-Purge: 1" \
"https://api.fastly.com/service/$FASTLY_SERVICE_ID/purge/site-$PROJECT"
fi
# Warm the cache with recursive wget.
if [ -z "$NO_WARM" ]; then
echo "Warming Fastly cache..."
wget \
--recursive \
--delete-after \
--quiet \
"https://$PROJECT_URL/"
fi

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 B

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 506 B

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 B

After

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 978 B

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -14,7 +14,7 @@ dedicated users willing to help through various mediums.
**IRC:** `#packer-tool` on Freenode.
**Mailing List:** [Packer Google
Group](http://groups.google.com/group/packer-tool)
Group](https://groups.google.com/group/packer-tool)
**Bug Tracker:** [Issue tracker on
GitHub](https://github.com/mitchellh/packer/issues). Please only use this for
@ -31,14 +31,14 @@ list as contributors come and go.
<div class="person">
<img class="pull-left" src="http://www.gravatar.com/avatar/54079122b67de9677c1f93933ce8b63a.png?s=125">
<img class="pull-left" src="https://www.gravatar.com/avatar/54079122b67de9677c1f93933ce8b63a.png?s=125">
<div class="bio">
<h3>Mitchell Hashimoto (<a href="https://github.com/mitchellh">@mitchellh</a>)</h3>
<p>
Mitchell Hashimoto is the creator of Packer. He developed the
core of Packer as well as the Amazon, VirtualBox, and VMware
builders. In addition to Packer, Mitchell is the creator of
<a href="http://www.vagrantup.com">Vagrant</a>. He is self
<a href="https://www.vagrantup.com">Vagrant</a>. He is self
described as "automation obsessed."
</p>
</div>
@ -47,7 +47,7 @@ list as contributors come and go.
<div class="person">
<img class="pull-left" src="http://www.gravatar.com/avatar/2acc31dd6370a54b18f6755cd0710ce6.png?s=125">
<img class="pull-left" src="https://www.gravatar.com/avatar/2acc31dd6370a54b18f6755cd0710ce6.png?s=125">
<div class="bio">
<h3>Jack Pearkes (<a href="https://github.com/pearkes">@pearkes</a>)</h3>
<p>
@ -60,7 +60,7 @@ list as contributors come and go.
<div class="person">
<img class="pull-left" src="http://www.gravatar.com/avatar/2f7fc9cb7558e3ea48f5a86fa90a78da.png?s=125">
<img class="pull-left" src="https://www.gravatar.com/avatar/2f7fc9cb7558e3ea48f5a86fa90a78da.png?s=125">
<div class="bio">
<h3>Mark Peek (<a href="https://github.com/markpeek">@markpeek</a>)</h3>
<p>
@ -75,7 +75,7 @@ list as contributors come and go.
<div class="person">
<img class="pull-left" src="http://www.gravatar.com/avatar/1fca64df3d7db1e2f258a8956d2b0aff.png?s=125">
<img class="pull-left" src="https://www.gravatar.com/avatar/1fca64df3d7db1e2f258a8956d2b0aff.png?s=125">
<div class="bio">
<h3>Ross Smith II (<a href="https://github.com/rasa" target="_blank">@rasa</a>)</h3>
<p>
@ -90,7 +90,7 @@ open source enthusiast, published author, and freelance consultant.
<div class="person">
<img class="pull-left" src="http://www.gravatar.com/avatar/c9f6bf7b5b865012be5eded656ebed7d.png?s=125">
<img class="pull-left" src="https://www.gravatar.com/avatar/c9f6bf7b5b865012be5eded656ebed7d.png?s=125">
<div class="bio">
<h3>Rickard von Essen<br/>(<a href="https://github.com/rickard-von-essen" target="_blank">@rickard-von-essen</a>)</h3>
<p>

View File

@ -16,7 +16,7 @@ The `amazon-chroot` Packer builder is able to create Amazon AMIs backed by an
EBS volume as the root device. For more information on the difference between
instance storage and EBS-backed instances, see the ["storage for the root
device" section in the EC2
documentation](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device).
documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device).
The difference between this builder and the `amazon-ebs` builder is that this
builder is able to build an EBS-backed AMI without launching a new EC2 instance.
@ -34,7 +34,7 @@ account, it is up to you to use, delete, etc. the AMI.
This builder works by creating a new EBS volume from an existing source AMI and
attaching it into an already-running EC2 instance. Once attached, a
[chroot](http://en.wikipedia.org/wiki/Chroot) is used to provision the system
[chroot](https://en.wikipedia.org/wiki/Chroot) is used to provision the system
within that volume. After provisioning, the volume is detached, snapshotted, and
an AMI is made.

View File

@ -13,10 +13,10 @@ page_title: 'Amazon AMI Builder (EBS backed)'
Type: `amazon-ebs`
The `amazon-ebs` Packer builder is able to create Amazon AMIs backed by EBS
volumes for use in [EC2](http://aws.amazon.com/ec2/). For more information on
volumes for use in [EC2](https://aws.amazon.com/ec2/). For more information on
the difference between EBS-backed instances and instance-store backed instances,
see the ["storage for the root device" section in the EC2
documentation](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device).
documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device).
This builder builds an AMI by launching an EC2 instance from a source AMI,
provisioning that running machine, and then creating an AMI from that machine.
@ -72,7 +72,7 @@ builder.
example, "/dev/sdh" or "xvdh"). Required when specifying `volume_size`.
- `virtual_name` (string) - The virtual device name. See the documentation on
[Block Device
Mapping](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_BlockDeviceMapping.html)
Mapping](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_BlockDeviceMapping.html)
for more information
- `snapshot_id` (string) - The ID of the snapshot
- `volume_type` (string) - The volume type. gp2 for General Purpose (SSD)
@ -87,7 +87,7 @@ builder.
block device mapping of the AMI
- `iops` (integer) - The number of I/O operations per second (IOPS) that the
volume supports. See the documentation on
[IOPs](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html)
[IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html)
for more information
- `ami_description` (string) - The description to set for the
resulting AMI(s). By default this description is empty.
@ -117,7 +117,7 @@ builder.
instance in. Leave this empty to allow Amazon to auto-assign.
- `ebs_optimized` (boolean) - Mark instance as [EBS
Optimized](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html).
Optimized](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html).
Default `false`.
- `enhanced_networking` (boolean) - Enable enhanced
@ -128,7 +128,7 @@ builder.
AMI if one with the same name already exists. Default `false`.
- `iam_instance_profile` (string) - The name of an [IAM instance
profile](http://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
to launch the EC2 instance with.
- `launch_block_device_mappings` (array of block device mappings) - Add the
@ -208,8 +208,8 @@ Here is a basic example. It is completely valid except for the access keys:
"access_key": "YOUR KEY HERE",
"secret_key": "YOUR SECRET KEY HERE",
"region": "us-east-1",
"source_ami": "ami-de0d9eb7",
"instance_type": "t1.micro",
"source_ami": "ami-72b9e018",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "packer-quick-start {{timestamp}}"
}
@ -237,8 +237,8 @@ the /dev/sdb and /dev/sdc block device mappings to the finished AMI.
"access_key": "YOUR KEY HERE",
"secret_key": "YOUR SECRET KEY HERE",
"region": "us-east-1",
"source_ami": "ami-de0d9eb7",
"instance_type": "t1.micro",
"source_ami": "ami-72b9e018",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "packer-quick-start {{timestamp}}",
"ami_block_device_mappings": [
@ -265,8 +265,8 @@ Here is an example using the optional AMI tags. This will add the tags
"access_key": "YOUR KEY HERE",
"secret_key": "YOUR SECRET KEY HERE",
"region": "us-east-1",
"source_ami": "ami-de0d9eb7",
"instance_type": "t1.micro",
"source_ami": "ami-72b9e018",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "packer-quick-start {{timestamp}}",
"tags": {

View File

@ -16,7 +16,7 @@ The `amazon-instance` Packer builder is able to create Amazon AMIs backed by
instance storage as the root device. For more information on the difference
between instance storage and EBS-backed instances, see the ["storage for the
root device" section in the EC2
documentation](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device).
documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device).
This builder builds an AMI by launching an EC2 instance from an existing
instance-storage backed AMI, provisioning that running machine, and then
@ -29,7 +29,7 @@ The builder does *not* manage AMIs. Once it creates an AMI and stores it in your
account, it is up to you to use, delete, etc. the AMI.
-&gt; **Note** This builder requires that the [Amazon EC2 AMI
Tools](http://aws.amazon.com/developertools/368) are installed onto the machine.
Tools](https://aws.amazon.com/developertools/368) are installed onto the machine.
This can be done within a provisioner, but must be done before the builder
finishes running.
@ -93,7 +93,7 @@ builder.
example, "/dev/sdh" or "xvdh"). Required when specifying `volume_size`.
- `virtual_name` (string) - The virtual device name. See the documentation on
[Block Device
Mapping](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_BlockDeviceMapping.html)
Mapping](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_BlockDeviceMapping.html)
for more information
- `snapshot_id` (string) - The ID of the snapshot
- `volume_type` (string) - The volume type. gp2 for General Purpose (SSD)
@ -108,7 +108,7 @@ builder.
block device mapping of the AMI
- `iops` (integer) - The number of I/O operations per second (IOPS) that the
volume supports. See the documentation on
[IOPs](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html)
[IOPs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_EbsBlockDevice.html)
for more information
- `ami_description` (string) - The description to set for the
resulting AMI(s). By default this description is empty.
@ -158,7 +158,7 @@ builder.
the "custom bundle commands" section below for more information.
- `ebs_optimized` (boolean) - Mark instance as [EBS
Optimized](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html).
Optimized](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html).
Default `false`.
- `enhanced_networking` (boolean) - Enable enhanced
@ -169,7 +169,7 @@ builder.
AMI if one with the same name already exists. Default `false`.
- `iam_instance_profile` (string) - The name of an [IAM instance
profile](http://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
to launch the EC2 instance with.
- `launch_block_device_mappings` (array of block device mappings) - Add the

View File

@ -23,7 +23,7 @@ Packer supports the following builders at the moment:
- [amazon-chroot](/docs/builders/amazon-chroot.html) - Create EBS-backed AMIs
from an existing EC2 instance by mounting the root device and using a
[Chroot](http://en.wikipedia.org/wiki/Chroot) environment to provision
[Chroot](https://en.wikipedia.org/wiki/Chroot) environment to provision
that device. This is an **advanced builder and should not be used by
newcomers**. However, it is also the fastest way to build an EBS-backed AMI
since no new EC2 instance needs to be launched.
@ -49,7 +49,7 @@ Credentials are resolved in the following order:
1. Values hard-coded in the packer template are always authoritative.
2. *Variables* in the packer template may be resolved from command-line flags
or from environment variables. Please read about [User
Variables](https://packer.io/docs/templates/user-variables.html)
Variables](https://www.packer.io/docs/templates/user-variables.html)
for details.
3. If no credentials are found, packer falls back to automatic lookup.
@ -63,7 +63,7 @@ following steps:
- First `AWS_SECRET_ACCESS_KEY`, then `AWS_SECRET_KEY`
2. Look for [local AWS configuration
files](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files)
files](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files)
- First `~/.aws/credentials`
- Next based on `AWS_PROFILE`
@ -80,7 +80,7 @@ packer build on your workstation, in Atlas, or on another build server.
## Using an IAM Instance Profile
If AWS keys are not specified in the template, a
[credentials](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files)
[credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files)
file or through environment variables Packer will use credentials provided by
the instance's IAM profile, if it has one.
@ -97,6 +97,7 @@ Packer to work:
"ec2:DeleteVolume",
"ec2:CreateKeypair",
"ec2:DeleteKeypair",
"ec2:DescribeSubnets",
"ec2:CreateSecurityGroup",
"ec2:DeleteSecurityGroup",
"ec2:AuthorizeSecurityGroupIngress",
@ -131,7 +132,7 @@ roles, you may encounter an error like this one:
==> amazon-ebs: Error launching source instance: You are not authorized to perform this operation.
You can read more about why this happens on the [Amazon Security
Blog](http://blogs.aws.amazon.com/security/post/Tx3M0IFB5XBOCQX/Granting-Permission-to-Launch-EC2-Instances-with-IAM-Roles-PassRole-Permission).
Blog](https://blogs.aws.amazon.com/security/post/Tx3M0IFB5XBOCQX/Granting-Permission-to-Launch-EC2-Instances-with-IAM-Roles-PassRole-Permission).
The example policy below may help packer work with IAM roles. Note that this
example provides more than the minimal set of permissions needed for packer to
work, but specifics will depend on your use-case.

View File

@ -14,7 +14,7 @@ page_title: DigitalOcean Builder
Type: `digitalocean`
The `digitalocean` Packer builder is able to create new images for use with
[DigitalOcean](http://www.digitalocean.com). The builder takes a source image,
[DigitalOcean](https://www.digitalocean.com). The builder takes a source image,
runs any provisioning necessary on the image after launching it, then snapshots
it into a reusable image. This reusable image can then be used as the foundation
of new servers that are launched within DigitalOcean.

View File

@ -11,7 +11,7 @@ page_title: Docker Builder
Type: `docker`
The `docker` Packer builder builds [Docker](http://www.docker.io) images using
The `docker` Packer builder builds [Docker](https://www.docker.io) images using
Docker. The builder starts a Docker container, runs provisioners within this
container, then exports the container for reuse or commits the image.
@ -26,7 +26,7 @@ the section on [Dockerfiles](#toc_8).
The Docker builder must run on a machine that has Docker installed. Therefore
the builder only works on machines that support Docker (modern Linux machines).
If you want to use Packer to build Docker containers on another platform, use
[Vagrant](http://www.vagrantup.com) to start a Linux environment, then run
[Vagrant](https://www.vagrantup.com) to start a Linux environment, then run
Packer within that environment.
## Basic Example: Export
@ -75,7 +75,7 @@ You must specify (only) one of `commit`, `discard`, or `export_path`.
- `discard` (boolean) - Throw away the container when the build is complete.
This is useful for the [artifice
post-processor](https://packer.io/docs/post-processors/artifice.html).
post-processor](https://www.packer.io/docs/post-processors/artifice.html).
- `export_path` (string) - The path where the final container will be exported
as a tar file.
@ -214,6 +214,42 @@ nearly-identical sequence definitions, as demonstrated by the example below:
}
```
<span id="amazon-ec2-container-registry"></span>
## Amazon EC2 Container Registry
Packer can tag and push images for use in
[Amazon EC2 Container Registry](https://aws.amazon.com/ecr/). The post
processors work as described above and example configuration properties are
shown below:
``` {.javascript}
{
"post-processors": [
[
{
"type": "docker-tag",
"repository": "12345.dkr.ecr.us-east-1.amazonaws.com/packer",
"tag": "0.7"
},
{
"type": "docker-push",
"login": true,
"login_email": "none",
"login_username": "AWS",
"login_password": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"login_server": "https://12345.dkr.ecr.us-east-1.amazonaws.com/"
}
]
]
}
```
See the
[AWS documentation](https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html)
for steps to obtain Amazon ECR registry credentials.
## Dockerfiles
This builder allows you to build Docker images *without* Dockerfiles.

View File

@ -118,6 +118,9 @@ builder.
Not required if you run Packer on a GCE instance with a service account.
Instructions for creating file or using service accounts are above.
- `address` (string) - The name of a pre-allocated static external IP address.
Note, must be the name and not the actual IP address.
- `disk_size` (integer) - The size of the disk in GB. This defaults to `10`,
which is 10GB.

View File

@ -11,7 +11,7 @@ page_title: 'Parallels Builder (from an ISO)'
Type: `parallels-iso`
The Parallels Packer builder is able to create [Parallels Desktop for
Mac](http://www.parallels.com/products/desktop/) virtual machines and export
Mac](https://www.parallels.com/products/desktop/) virtual machines and export
them in the PVM format, starting from an ISO image.
The builder builds a virtual machine by creating a new virtual machine from

View File

@ -12,7 +12,7 @@ page_title: 'Parallels Builder (from a PVM)'
Type: `parallels-pvm`
This Parallels builder is able to create [Parallels Desktop for
Mac](http://www.parallels.com/products/desktop/) virtual machines and export
Mac](https://www.parallels.com/products/desktop/) virtual machines and export
them in the PVM format, starting from an existing PVM (exported virtual machine
image).

View File

@ -9,7 +9,7 @@ page_title: Parallels Builder
# Parallels Builder
The Parallels Packer builder is able to create [Parallels Desktop for
Mac](http://www.parallels.com/products/desktop/) virtual machines and export
Mac](https://www.parallels.com/products/desktop/) virtual machines and export
them in the PVM format.
Packer actually comes with multiple builders able to create Parallels machines,
@ -30,8 +30,8 @@ the following Parallels builders:
## Requirements
In addition to [Parallels Desktop for
Mac](http://www.parallels.com/products/desktop/) this requires the [Parallels
Virtualization SDK](http://www.parallels.com/downloads/desktop/).
Mac](https://www.parallels.com/products/desktop/) this requires the [Parallels
Virtualization SDK](https://www.parallels.com/downloads/desktop/).
The SDK can be installed by downloading and following the instructions in the
dmg.

View File

@ -322,7 +322,7 @@ directory of the SSH user.
In order to perform extra customization of the virtual machine, a template can
define extra calls to `VBoxManage` to perform.
[VBoxManage](http://www.virtualbox.org/manual/ch08.html) is the command-line
[VBoxManage](https://www.virtualbox.org/manual/ch08.html) is the command-line
interface to VirtualBox where you can completely control VirtualBox. It can be
used to do things such as set RAM, CPUs, etc.

View File

@ -226,7 +226,7 @@ directory of the SSH user.
In order to perform extra customization of the virtual machine, a template can
define extra calls to `VBoxManage` to perform.
[VBoxManage](http://www.virtualbox.org/manual/ch08.html) is the command-line
[VBoxManage](https://www.virtualbox.org/manual/ch08.html) is the command-line
interface to VirtualBox where you can completely control VirtualBox. It can be
used to do things such as set RAM, CPUs, etc.

View File

@ -9,7 +9,7 @@ page_title: VirtualBox Builder
# VirtualBox Builder
The VirtualBox Packer builder is able to create
[VirtualBox](http://www.virtualbox.org) virtual machines and export them in the
[VirtualBox](https://www.virtualbox.org) virtual machines and export them in the
OVA or OVF format.
Packer actually comes with multiple builders able to create VirtualBox machines,

View File

@ -15,12 +15,12 @@ Type: `vmware-iso`
This VMware Packer builder is able to create VMware virtual machines from an ISO
file as a source. It currently supports building virtual machines on hosts
running [VMware Fusion](http://www.vmware.com/products/fusion/overview.html) for
running [VMware Fusion](https://www.vmware.com/products/fusion/overview.html) for
OS X, [VMware
Workstation](http://www.vmware.com/products/workstation/overview.html) for Linux
and Windows, and [VMware Player](http://www.vmware.com/products/player/) on
Workstation](https://www.vmware.com/products/workstation/overview.html) for Linux
and Windows, and [VMware Player](https://www.vmware.com/products/player/) on
Linux. It can also build machines directly on [VMware vSphere
Hypervisor](http://www.vmware.com/products/vsphere-hypervisor/) using SSH as
Hypervisor](https://www.vmware.com/products/vsphere-hypervisor/) using SSH as
opposed to the vSphere API.
The builder builds a virtual machine by creating a new virtual machine from
@ -105,7 +105,7 @@ builder.
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) for desktop
User's Guide](https://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 place onto a floppy
@ -187,6 +187,10 @@ builder.
the remote machine. By default this is empty. This only has an effect if
`remote_type` is enabled.
- `remote_private_key_file` (string) - The path to the PEM encoded private key
file for the user used to access the remote machine. By default this is empty.
This only has an effect if `remote_type` is enabled.
- `remote_type` (string) - The type of remote machine that will be used to
build this VM rather than a local desktop product. The only value accepted
for this currently is "esx5". If this is not set, a desktop product will
@ -398,6 +402,8 @@ modify as well:
- `remote_password` - The SSH password for access to the remote machine.
- `remote_private_key_file` - The SSH key for access to the remote machine.
- `format` (string) - Either "ovf", "ova" or "vmx", this specifies the output
format of the exported virtual machine. This defaults to "ovf".
Before using this option, you need to install `ovftool`.

View File

@ -15,10 +15,10 @@ Type: `vmware-vmx`
This VMware Packer builder is able to create VMware virtual machines from an
existing VMware virtual machine (a VMX file). It currently supports building
virtual machines on hosts running [VMware Fusion
Professional](http://www.vmware.com/products/fusion-professional/) for OS X,
[VMware Workstation](http://www.vmware.com/products/workstation/overview.html)
Professional](https://www.vmware.com/products/fusion-professional/) for OS X,
[VMware Workstation](https://www.vmware.com/products/workstation/overview.html)
for Linux and Windows, and [VMware
Player](http://www.vmware.com/products/player/) on Linux.
Player](https://www.vmware.com/products/player/) on Linux.
The builder builds a virtual machine by cloning the VMX file using the clone
capabilities introduced in VMware Fusion Professional 6, Workstation 10, and

View File

@ -26,7 +26,7 @@ both the post-processor and push commands can be used independently.
scripts, to Atlas. Take care not to upload files that you don't intend to, like
secrets or large binaries. **If you have secrets in your Packer template, you
should [move them into environment
variables](https://packer.io/docs/templates/user-variables.html).**
variables](https://www.packer.io/docs/templates/user-variables.html).**
Most push behavior is [configured in your packer
template](/docs/templates/push.html). You can override or supplement your
@ -34,10 +34,6 @@ configuration using the options below.
## Options
- `-message` - A message to identify the purpose or changes in this Packer
template much like a VCS commit message. This message will be passed to the
Packer build service. This option is also available as a short option `-m`.
- `-token` - Your access token for the Atlas API.
-&gt; Login to Atlas to [generate an Atlas
@ -59,7 +55,7 @@ you can also use `-token` on the command line.
Push a Packer template:
``` {.shell}
$ packer push -m "Updating the apache version" template.json
$ packer push template.json
```
Push a Packer template with a custom token:
@ -81,7 +77,7 @@ download it during the packer run.
If you want to build a private `.iso` file you can upload the `.iso` to a secure
file hosting service like [Amazon
S3](http://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURL.html),
S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURL.html),
[Google Cloud
Storage](https://cloud.google.com/storage/docs/gsutil/commands/signurl), or
[Azure File

View File

@ -157,7 +157,7 @@ it would be convenient to cache the file. This sort of caching is a core part of
Packer that is exposed to builders.
The cache interface is `packer.Cache`. It behaves much like a Go
[RWMutex](http://golang.org/pkg/sync/#RWMutex). The builder requests a "lock" on
[RWMutex](https://golang.org/pkg/sync/#RWMutex). The builder requests a "lock" on
certain cache keys, and is given exclusive access to that key for the duration
of the lock. This locking mechanism allows multiple builders to share cache data
even though they're running in parallel.

View File

@ -14,7 +14,7 @@ reading this, it is assumed that you're comfortable with Packer and also know
the [basics of how Plugins work](/docs/extend/plugins.html), from a user
standpoint.
Packer plugins must be written in [Go](http://golang.org/), so it is also
Packer plugins must be written in [Go](https://golang.org/), so it is also
assumed that you're familiar with the language. This page will not be a Go
language tutorial. Thankfully, if you are familiar with Go, the Go toolchain
makes it extremely easy to develop Packer plugins.
@ -36,7 +36,7 @@ uses, because they're completely isolated into the process space of the plugin
itself.
And, thanks to Go's
[interfaces](http://golang.org/doc/effective_go.html#interfaces_and_types), it
[interfaces](https://golang.org/doc/effective_go.html#interfaces_and_types), it
doesn't even look like inter-process communication is occurring. You just use
the interfaces like normal, but in fact they're being executed in a remote
process. Pretty cool.

View File

@ -32,9 +32,9 @@ After unzipping the package, the directory should contain a set of binary
programs, such as `packer`, `packer-build-amazon-ebs`, etc. The final step to
installation is to make sure the directory you installed Packer to is on the
PATH. See [this
page](http://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux)
page](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux)
for instructions on setting the PATH on Linux and Mac. [This
page](http://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows)
page](https://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows)
contains instructions for setting the PATH on Windows.
## Verifying the Installation

View File

@ -65,7 +65,7 @@ example:
$env:PACKER_LOG_PATH="packerlog.txt"
If you find a bug with Packer, please include the detailed log by using a
service such as [gist](http://gist.github.com).
service such as [gist](https://gist.github.com).
## Issues Installing Ubuntu Packages

View File

@ -25,9 +25,9 @@ extracting the docker container and throwing away the EC2 instance.
After overriding the artifact with artifice, you can use it with other
post-processors like
[compress](https://packer.io/docs/post-processors/compress.html),
[docker-push](https://packer.io/docs/post-processors/docker-push.html),
[Atlas](https://packer.io/docs/post-processors/atlas.html), or a third-party
[compress](https://www.packer.io/docs/post-processors/compress.html),
[docker-push](https://www.packer.io/docs/post-processors/docker-push.html),
[Atlas](https://www.packer.io/docs/post-processors/atlas.html), or a third-party
post-processor.
Artifice allows you to use the familiar packer workflow to create a fresh,
@ -67,7 +67,7 @@ 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
2. Installs a [consul](https://www.consul.io/) release
3. Downloads the consul binary
4. Packages it into a `.tar.gz` file
5. Uploads it to Atlas.

View File

@ -38,7 +38,7 @@ Here is an example workflow:
example `hashicorp/foobar`, to create the artifact in Atlas or update the
version if the artifact already exists
3. The new version is ready and available to be used in deployments with a tool
like [Terraform](https://terraform.io)
like [Terraform](https://www.terraform.io)
## Configuration
@ -88,8 +88,8 @@ you can also use `token` configuration option.
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "us-east-1",
"source_ami": "ami-de0d9eb7",
"instance_type": "t1.micro",
"source_ami": "ami-72b9e018",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "atlas-example {{timestamp}}"
}],

View File

@ -18,12 +18,12 @@ Type: `vagrant-cloud`
The Packer Vagrant Cloud post-processor receives a Vagrant box from the
`vagrant` post-processor and pushes it to Vagrant Cloud. [Vagrant
Cloud](https://vagrantcloud.com) hosts and serves boxes to Vagrant, allowing you
Cloud](https://atlas.hashicorp.com) hosts and serves boxes to Vagrant, allowing you
to version and distribute boxes to an organization in a simple way.
You'll need to be familiar with Vagrant Cloud, have an upgraded account to
enable box hosting, and be distributing your box via the [shorthand
name](http://docs.vagrantup.com/v2/cli/box.html) configuration.
name](https://docs.vagrantup.com/v2/cli/box.html) configuration.
## Workflow

View File

@ -13,7 +13,7 @@ page_title: 'Vagrant Post-Processor'
Type: `vagrant`
The Packer Vagrant post-processor takes a build and converts the artifact into a
valid [Vagrant](http://www.vagrantup.com) box, if it can. This lets you use
valid [Vagrant](https://www.vagrantup.com) box, if it can. This lets you use
Packer to automatically create arbitrarily complex Vagrant boxes, and is in fact
how the official boxes distributed by Vagrant are created.
@ -22,7 +22,7 @@ If you've never used a post-processor before, please read the documentation on
knowledge will be expected for the remainder of this document.
Because Vagrant boxes are
[provider-specific](http://docs.vagrantup.com/v2/boxes/format.html), the Vagrant
[provider-specific](https://docs.vagrantup.com/v2/boxes/format.html), the Vagrant
post-processor is hardcoded to understand how to convert the artifacts of
certain builders into proper boxes for their respective providers.

View File

@ -15,7 +15,7 @@ Type: `ansible-local`
The `ansible-local` Packer provisioner configures Ansible to run on the machine
by Packer from local Playbook and Role files. Playbooks and Roles can be
uploaded from your local machine to the remote machine. Ansible is run in [local
mode](http://docs.ansible.com/playbooks_delegation.html#local-playbooks) via the
mode](https://docs.ansible.com/ansible/playbooks_delegation.html#local-playbooks) via the
`ansible-playbook` command.
-&gt; **Note:** Ansible will *not* be installed automatically by this

View File

@ -50,6 +50,10 @@ configuration is actually required.
should use a custom configuration template. See the dedicated "Chef
Configuration" section below for more details.
- `encrypted_data_bag_secret_path` (string) - The path to the file containing
the secret for encrypted data bags. By default, this is empty, so no secret
will be available.
- `execute_command` (string) - The command used to execute Chef. This has
various [configuration template
variables](/docs/templates/configuration-templates.html) available. See
@ -71,9 +75,9 @@ configuration is actually required.
then the sudo will be omitted.
- `run_list` (array of strings) - The [run
list](http://docs.chef.io/essentials_node_object_run_lists.html)
for Chef. By default this is empty, and will use the run list sent down by
the Chef Server.
list](http://docs.chef.io/essentials_node_object_run_lists.html) for Chef.
By default this is empty, and will use the run list sent down by the
Chef Server.
- `server_url` (string) - The URL to the Chef server. This is required.
@ -136,6 +140,7 @@ This template is a [configuration
template](/docs/templates/configuration-templates.html) and has a set of
variables available to use:
- `EncryptedDataBagSecretPath` - The path to the encrypted data bag secret
- `NodeName` - The node name set in the configuration.
- `ServerUrl` - The URL of the Chef Server set in the configuration.
- `ValidationKeyPath` - Path to the validation key, if it is set.
@ -181,3 +186,65 @@ to 777. This is to ensure that Packer can upload and make use of that directory.
However, once the machine is created, you usually don't want to keep these
directories with those permissions. To change the permissions on the
directories, append a shell provisioner after Chef to modify them.
## Examples
### Chef Client Local Mode
The following example shows how to run the `chef-cilent` provisioner in local
mode, while passing a `run_list` using a variable.
**Local environment variables**
# Machines Chef directory
export PACKER_CHEF_DIR=/var/chef-packer
# Comma separated run_list
export PACKER_CHEF_RUN_LIST="recipe[apt],recipe[nginx]"
...
**Packer variables**
Set the necessary Packer variables using environment variables or provide a [var
file](/docs/templates/user-variables.html).
``` {.liquid}
"variables": {
"chef_dir": "{{env `PACKER_CHEF_DIR`}}",
"chef_run_list": "{{env `PACKER_CHEF_RUN_LIST`}}",
"chef_client_config_tpl": "{{env `PACKER_CHEF_CLIENT_CONFIG_TPL`}}",
"packer_chef_bootstrap_dir": "{{env `PACKER_CHEF_BOOTSTRAP_DIR`}}" ,
"packer_uid": "{{env `PACKER_UID`}}",
"packer_gid": "{{env `PACKER_GID`}}"
}
```
**Setup the** `chef-client` **provisioner**
Make sure we have the correct directories and permissions for the `chef-client`
provisioner. You will need to bootstrap the Chef run by providing the necessary
cookbooks using Berkshelf or some other means.
``` {.liquid}
{
"type": "file",
"source": "{{user `packer_chef_bootstrap_dir`}}",
"destination": "/tmp/bootstrap"
},
{
"type": "shell",
"inline": [
"sudo mkdir -p {{user `chef_dir`}}",
"sudo mkdir -p /tmp/packer-chef-client",
"sudo chown {{user `packer_uid`}}.{{user `packer_gid`}} /tmp/packer-chef-client",
"sudo sh /tmp/bootstrap/bootstrap.sh"
]
},
{
"type": "chef-client",
"server_url": "http://localhost:8889",
"config_template": "{{user `chef_client_config_tpl`}}/client.rb.tpl",
"skip_clean_node": true,
"skip_clean_client": true,
"run_list": "{{user `chef_run_list`}}"
}
```

Some files were not shown because too many files have changed in this diff Show More