Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 324581ac9c | |||
| 61023f31fd | |||
| 57e38908f0 | |||
| 348e00422e | |||
| a276fa147a | |||
| 7912e496aa | |||
| 1b532fc816 | |||
| da8e215536 | |||
| 4059ed75f5 | |||
| 127905e855 | |||
| 66445ecd2d | |||
| 37dc411f30 | |||
| 7ce9992357 | |||
| f45d315be4 | |||
| 0ded72670f | |||
| f47d9f1b1f | |||
| b23425f637 | |||
| 09489da149 | |||
| 5054b1becc | |||
| bbc5bc0658 | |||
| e212c27175 | |||
| f1e6f8eac1 | |||
| a67948f155 | |||
| d0e9242b3d | |||
| 9216f43463 | |||
| 412df59ea5 | |||
| 04b269461c | |||
| 46ce0529dd | |||
| fbd3796377 | |||
| 31cad234f2 | |||
| 1d066082a5 | |||
| 4c3fa0ef26 | |||
| 42cf9ef064 | |||
| 9eda2031d2 | |||
| 6a185b7c64 | |||
| a6c56aa4e2 | |||
| f6878d6a2a | |||
| 7fe51022ca | |||
| 0436457fd7 | |||
| 8cdf8ca442 | |||
| bb72a0c0ce | |||
| 26ceea0c36 | |||
| 04a8758811 | |||
| 978af9188f | |||
| da12c73726 | |||
| 971eac1701 | |||
| 9219a606a3 | |||
| f3629dbaf7 | |||
| 8dc587967e | |||
| 93b9f3cb80 | |||
| da90c22c35 | |||
| 1ada06b2d7 | |||
| 8c21916606 |
@@ -1,3 +1,32 @@
|
||||
## 1.5.1 (December 20, 2019)
|
||||
This was a fast-follow release to fix a number of panics that we introduced when
|
||||
making changes for HCL2.
|
||||
|
||||
### IMPROVEMENTS:
|
||||
* builder/alicloud: Add show_expired option for describing images [GH-8425]
|
||||
|
||||
### Bug Fixes:
|
||||
* builder/cloudstack: Fix panics associated with loading config [GH-8513]
|
||||
* builder/hyperv/iso: Fix panics associated with loading config [GH-8513]
|
||||
* builder/hyperv/vmcx: Fix panics associated with loading config [GH-8513]
|
||||
* builder/jdcloud: Update jdcloud statebag to use pointers for config [GH-8518]
|
||||
* builder/linode: Fix panics associated with loading config [GH-8513]
|
||||
* builder/lxc: Fix panics associated with loading config [GH-8513]
|
||||
* builder/lxd: Fix panics associated with loading config [GH-8513]
|
||||
* builder/oneandone: Fix panics associated with loading config [GH-8513]
|
||||
* builder/oracle/classic: Fix panics associated with loading config [GH-8513]
|
||||
* builder/oracle/oci: Fix panics associated with loading config [GH-8513]
|
||||
* builder/osc/bsuvolume: Fix panics associated with loading config [GH-8513]
|
||||
* builder/parallels/pvm: Fix panics associated with loading config [GH-8513]
|
||||
* builder/profitbricks: Fix panics associated with loading config [GH-8513]
|
||||
* builder/scaleway: Fix panics associated with loading config [GH-8513]
|
||||
* builder/vagrant: Fix panics associated with loading config [GH-8513]
|
||||
* builder/virtualbox/ovf: Fix panics associated with loading config [GH-8513]
|
||||
* builder/virtualbox: Configure NAT interface before forwarded port mapping
|
||||
#8514
|
||||
* post-processor/vagrant-cloud: Configure NAT interface before forwarded port
|
||||
mapping [GH-8514]
|
||||
|
||||
## 1.5.0 (December 18, 2019)
|
||||
|
||||
### IMPROVEMENTS:
|
||||
@@ -11,6 +40,8 @@
|
||||
[GH-8342]
|
||||
* builder/hyperone: Update builder schema and tags [GH-8444]
|
||||
* builder/qemu: Add display template option for qemu. [GH-7676]
|
||||
* builder/qemu: Disk Size is now read as a string to support units. [GH-8320]
|
||||
[GH-7546]
|
||||
* builder/qemu: Add fixer to convert disk size from int to string [GH-8390]
|
||||
* builder/qemu: Disk Size is now read as a string to support units. [GH-8320]
|
||||
[GH-7546]
|
||||
@@ -23,6 +54,7 @@
|
||||
like Host IP, communicator password, and more. [GH-7866]
|
||||
* core: Various fixes to error handling. [GH-8343] [GH-8333] [GH-8316]
|
||||
[GH-8354] [GH-8361] [GH-8363] [GH-8370]
|
||||
* post-processor/docker-tag: Add support for multiple tags. [GH-8392]
|
||||
* post-processor/shell-local: Add "valid_exit_codes" option to shell-local.
|
||||
[GH-8401]
|
||||
* provisioner/chef-client: Add version selection option. [GH-8468]
|
||||
|
||||
@@ -26,6 +26,9 @@ type AlicloudAccessConfig struct {
|
||||
// The region validation can be skipped if this value is true, the default
|
||||
// value is false.
|
||||
AlicloudSkipValidation bool `mapstructure:"skip_region_validation" required:"false"`
|
||||
// The image validation can be skipped if this value is true, the default
|
||||
// value is false.
|
||||
AlicloudSkipImageValidation bool `mapstructure:"skip_image_validation" required:"false"`
|
||||
// STS access token, can be set through template or by exporting as
|
||||
// environment variable such as `export SECURITY_TOKEN=value`.
|
||||
SecurityToken string `mapstructure:"security_token" required:"false"`
|
||||
|
||||
@@ -57,6 +57,7 @@ type FlatConfig struct {
|
||||
AlicloudSecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
|
||||
AlicloudRegion *string `mapstructure:"region" required:"true" cty:"region"`
|
||||
AlicloudSkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
|
||||
AlicloudSkipImageValidation *bool `mapstructure:"skip_image_validation" required:"false" cty:"skip_image_validation"`
|
||||
SecurityToken *string `mapstructure:"security_token" required:"false" cty:"security_token"`
|
||||
AlicloudImageName *string `mapstructure:"image_name" required:"true" cty:"image_name"`
|
||||
AlicloudImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
|
||||
@@ -160,6 +161,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
|
||||
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
|
||||
"skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false},
|
||||
"skip_image_validation": &hcldec.AttrSpec{Name: "skip_image_validation", Type: cty.Bool, Required: false},
|
||||
"security_token": &hcldec.AttrSpec{Name: "security_token", Type: cty.String, Required: false},
|
||||
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
|
||||
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
|
||||
|
||||
@@ -33,14 +33,11 @@ func TestWaitForExpectedExceedRetryTimes(t *testing.T) {
|
||||
waitDone <- true
|
||||
}()
|
||||
|
||||
timeTolerance := 1 * time.Second
|
||||
select {
|
||||
case <-waitDone:
|
||||
if iter != defaultRetryTimes {
|
||||
t.Fatalf("WaitForExpected should terminate at the %d iterations", defaultRetryTimes)
|
||||
}
|
||||
case <-time.After(defaultRetryTimes*defaultRetryInterval + timeTolerance):
|
||||
t.Fatalf("WaitForExpected should terminate within %f seconds", (defaultRetryTimes*defaultRetryInterval + timeTolerance).Seconds())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ func (s *stepCheckAlicloudSourceImage) Run(ctx context.Context, state multistep.
|
||||
describeImagesRequest := ecs.CreateDescribeImagesRequest()
|
||||
describeImagesRequest.RegionId = config.AlicloudRegion
|
||||
describeImagesRequest.ImageId = config.AlicloudSourceImage
|
||||
if config.AlicloudSkipImageValidation {
|
||||
describeImagesRequest.ShowExpired = "true"
|
||||
}
|
||||
imagesResponse, err := client.DescribeImages(describeImagesRequest)
|
||||
if err != nil {
|
||||
return halt(state, err, "Error querying alicloud image")
|
||||
|
||||
@@ -53,7 +53,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("client", client)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
|
||||
@@ -183,7 +183,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
|
||||
@@ -223,7 +223,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
|
||||
@@ -46,7 +46,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
|
||||
steps := []multistep.Step{
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ func (s *stepCreateJDCloudInstance) Cleanup(state multistep.StateBag) {
|
||||
|
||||
func createElasticIp(state multistep.StateBag) (string, error) {
|
||||
|
||||
generalConfig := state.Get("config").(Config)
|
||||
generalConfig := state.Get("config").(*Config)
|
||||
regionId := generalConfig.RegionId
|
||||
credential := core.NewCredentials(generalConfig.AccessKey, generalConfig.SecretKey)
|
||||
vpcclient := vpcClient.NewVpcClient(credential)
|
||||
|
||||
@@ -47,7 +47,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (ret
|
||||
}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Setup the state bag
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
state.Put("wrappedCommand", CommandWrapper(wrappedCommand))
|
||||
|
||||
@@ -47,7 +47,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Setup the state bag
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
state.Put("wrappedCommand", CommandWrapper(wrappedCommand))
|
||||
|
||||
@@ -45,7 +45,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Setup the state bag and initial state for the steps
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
runID := fmt.Sprintf("%s_%s", b.config.ImageName, os.Getenv("PACKER_RUN_UUID"))
|
||||
// Populate the state bag
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
state.Put("client", client)
|
||||
|
||||
@@ -46,7 +46,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Populate the state bag
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
@@ -104,7 +104,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Setup the state bag and initial state for the steps
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("oapi", oapiconn)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
@@ -42,7 +42,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
|
||||
@@ -32,7 +32,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
steps := []multistep.Step{
|
||||
|
||||
@@ -44,7 +44,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("client", client)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
@@ -237,7 +237,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
|
||||
@@ -185,7 +185,7 @@ func (d *VBox42Driver) VBoxManage(args ...string) error {
|
||||
ShouldRetry: func(err error) bool {
|
||||
return strings.Contains(err.Error(), "VBOX_E_INVALID_OBJECT_STATE")
|
||||
},
|
||||
RetryDelay: func() time.Duration { return 2 * time.Minute },
|
||||
RetryDelay: func() time.Duration { return 1 * time.Minute },
|
||||
}.Run(ctx, func(ctx context.Context) error {
|
||||
_, err := d.VBoxManageWithOutput(args...)
|
||||
return err
|
||||
|
||||
@@ -63,9 +63,22 @@ func (s *StepForwardSSH) Run(ctx context.Context, state multistep.StateBag) mult
|
||||
s.l.Listener.Close() // free port, but don't unlock lock file
|
||||
sshHostPort = s.l.Port
|
||||
|
||||
// Make sure to configure the network interface to NAT
|
||||
command := []string{
|
||||
"modifyvm", vmName,
|
||||
"--nic1",
|
||||
"nat",
|
||||
}
|
||||
if err := driver.VBoxManage(command...); err != nil {
|
||||
err := fmt.Errorf("Failed to configure NAT interface: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Create a forwarded port mapping to the VM
|
||||
ui.Say(fmt.Sprintf("Creating forwarded port mapping for communicator (SSH, WinRM, etc) (host port %d)", sshHostPort))
|
||||
command := []string{
|
||||
command = []string{
|
||||
"modifyvm", vmName,
|
||||
"--natpf1",
|
||||
fmt.Sprintf("packercomm,tcp,127.0.0.1,%d,,%d", sshHostPort, guestPort),
|
||||
|
||||
@@ -109,70 +109,6 @@ func TestStepShutdown_shutdownTimeout(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepShutdown_shutdownDelay(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepShutdown)
|
||||
step.Command = "poweroff"
|
||||
step.Timeout = 5 * time.Second
|
||||
step.Delay = 2 * time.Second
|
||||
step.DisableShutdown = false
|
||||
|
||||
comm := new(packer.MockCommunicator)
|
||||
state.Put("communicator", comm)
|
||||
state.Put("vmName", "foo")
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
driver.IsRunningReturn = true
|
||||
start := time.Now()
|
||||
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
driver.Lock()
|
||||
defer driver.Unlock()
|
||||
driver.IsRunningReturn = false
|
||||
}()
|
||||
|
||||
// Test the run
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
testDuration := time.Since(start)
|
||||
if testDuration < 2500*time.Millisecond || testDuration > 2700*time.Millisecond {
|
||||
t.Fatalf("incorrect duration %s", testDuration)
|
||||
}
|
||||
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
step.Delay = 0
|
||||
|
||||
driver.IsRunningReturn = true
|
||||
start = time.Now()
|
||||
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
driver.Lock()
|
||||
defer driver.Unlock()
|
||||
driver.IsRunningReturn = false
|
||||
}()
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
testDuration = time.Since(start)
|
||||
if testDuration > 700*time.Millisecond {
|
||||
t.Fatalf("incorrect duration %s", testDuration)
|
||||
}
|
||||
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStepShutdown_DisableShutdown(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepShutdown)
|
||||
|
||||
@@ -42,7 +42,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
@@ -86,8 +86,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
Url: []string{b.config.SourcePath},
|
||||
},
|
||||
&StepImport{
|
||||
Name: b.config.VMName,
|
||||
ImportFlags: b.config.ImportFlags,
|
||||
Name: b.config.VMName,
|
||||
ImportFlags: b.config.ImportFlags,
|
||||
KeepRegistered: b.config.KeepRegistered,
|
||||
},
|
||||
&vboxcommon.StepAttachGuestAdditions{
|
||||
GuestAdditionsMode: b.config.GuestAdditionsMode,
|
||||
|
||||
@@ -11,8 +11,9 @@ import (
|
||||
|
||||
// This step imports an OVF VM into VirtualBox.
|
||||
type StepImport struct {
|
||||
Name string
|
||||
ImportFlags []string
|
||||
Name string
|
||||
ImportFlags []string
|
||||
KeepRegistered bool
|
||||
|
||||
vmName string
|
||||
}
|
||||
@@ -42,11 +43,10 @@ func (s *StepImport) Cleanup(state multistep.StateBag) {
|
||||
|
||||
driver := state.Get("driver").(vboxcommon.Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
config := state.Get("config").(*Config)
|
||||
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
if (config.KeepRegistered) && (!cancelled && !halted) {
|
||||
if (s.KeepRegistered) && (!cancelled && !halted) {
|
||||
ui.Say("Keeping virtual machine registered with VirtualBox host (keep_registered = true)")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -14,11 +14,8 @@ func TestStepImport_impl(t *testing.T) {
|
||||
|
||||
func TestStepImport(t *testing.T) {
|
||||
state := testState(t)
|
||||
cfg := testConfig(t)
|
||||
var c Config
|
||||
c.Prepare(cfg)
|
||||
state.Put("vm_path", "foo")
|
||||
state.Put("config", &c)
|
||||
|
||||
step := new(StepImport)
|
||||
step.Name = "bar"
|
||||
|
||||
@@ -46,16 +43,24 @@ func TestStepImport(t *testing.T) {
|
||||
} else if name != "bar" {
|
||||
t.Fatalf("bad: %#v", name)
|
||||
}
|
||||
}
|
||||
|
||||
// Test cleanup
|
||||
c.KeepRegistered = true
|
||||
func TestStepImport_Cleanup(t *testing.T) {
|
||||
state := testState(t)
|
||||
state.Put("vm_path", "foo")
|
||||
|
||||
step := new(StepImport)
|
||||
step.vmName = "bar"
|
||||
|
||||
driver := state.Get("driver").(*vboxcommon.DriverMock)
|
||||
|
||||
step.KeepRegistered = true
|
||||
step.Cleanup(state)
|
||||
|
||||
if driver.DeleteCalled {
|
||||
t.Fatal("delete should not be called")
|
||||
}
|
||||
|
||||
c.KeepRegistered = false
|
||||
state.Put(multistep.StateHalted, true)
|
||||
step.Cleanup(state)
|
||||
if !driver.DeleteCalled {
|
||||
t.Fatal("delete should be called")
|
||||
|
||||
@@ -42,7 +42,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
|
||||
@@ -61,7 +61,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", b.config)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("dir", dir)
|
||||
state.Put("driver", driver)
|
||||
|
||||
@@ -113,7 +113,8 @@ type SSH struct {
|
||||
// use this option with a key pair already configured in the source AMI,
|
||||
// leave the `ssh_keypair_name` blank. To associate an existing key pair in
|
||||
// AWS with the source instance, set the `ssh_keypair_name` field to the
|
||||
// name of the key pair.
|
||||
// name of the key pair. The environment variable `SSH_AUTH_SOCK` must be
|
||||
// set for this option to work properly.
|
||||
SSHAgentAuth bool `mapstructure:"ssh_agent_auth"`
|
||||
// If true, SSH agent forwarding will be disabled. Defaults to `false`.
|
||||
SSHDisableAgentForwarding bool `mapstructure:"ssh_disable_agent_forwarding"`
|
||||
|
||||
@@ -21,6 +21,7 @@ type FlatConfig struct {
|
||||
AlicloudSecretKey *string `mapstructure:"secret_key" required:"true" cty:"secret_key"`
|
||||
AlicloudRegion *string `mapstructure:"region" required:"true" cty:"region"`
|
||||
AlicloudSkipValidation *bool `mapstructure:"skip_region_validation" required:"false" cty:"skip_region_validation"`
|
||||
AlicloudSkipImageValidation *bool `mapstructure:"skip_image_validation" required:"false" cty:"skip_image_validation"`
|
||||
SecurityToken *string `mapstructure:"security_token" required:"false" cty:"security_token"`
|
||||
AlicloudImageName *string `mapstructure:"image_name" required:"true" cty:"image_name"`
|
||||
AlicloudImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
|
||||
@@ -132,6 +133,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
"secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false},
|
||||
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
|
||||
"skip_region_validation": &hcldec.AttrSpec{Name: "skip_region_validation", Type: cty.Bool, Required: false},
|
||||
"skip_image_validation": &hcldec.AttrSpec{Name: "skip_image_validation", Type: cty.Bool, Required: false},
|
||||
"security_token": &hcldec.AttrSpec{Name: "security_token", Type: cty.String, Required: false},
|
||||
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
|
||||
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
|
||||
|
||||
@@ -166,7 +166,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||
|
||||
// Set up the state
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", p.config)
|
||||
state.Put("config", &p.config)
|
||||
state.Put("client", p.client)
|
||||
state.Put("artifact", artifact)
|
||||
state.Put("artifactFilePath", artifact.Files()[0])
|
||||
|
||||
@@ -19,7 +19,7 @@ type stepCreateVersion struct {
|
||||
func (s *stepCreateVersion) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*VagrantCloudClient)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
config := state.Get("config").(Config)
|
||||
config := state.Get("config").(*Config)
|
||||
box := state.Get("box").(*Box)
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating version: %s", config.Version))
|
||||
|
||||
@@ -17,7 +17,7 @@ func (s *stepReleaseVersion) Run(ctx context.Context, state multistep.StateBag)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
box := state.Get("box").(*Box)
|
||||
version := state.Get("version").(*Version)
|
||||
config := state.Get("config").(Config)
|
||||
config := state.Get("config").(*Config)
|
||||
|
||||
ui.Say(fmt.Sprintf("Releasing version: %s", version.Version))
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ type stepVerifyBox struct {
|
||||
func (s *stepVerifyBox) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*VagrantCloudClient)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
config := state.Get("config").(Config)
|
||||
config := state.Get("config").(*Config)
|
||||
|
||||
ui.Say(fmt.Sprintf("Verifying box is accessible: %s", config.Tag))
|
||||
|
||||
|
||||
@@ -125,8 +125,6 @@ type KnifeTemplate struct {
|
||||
func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
|
||||
|
||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
// Create passthrough for build-generated data
|
||||
p.config.ctx.Data = packer.BasicPlaceholderData()
|
||||
err := config.Decode(&p.config, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &p.config.ctx,
|
||||
|
||||
@@ -91,9 +91,6 @@ func (p *Provisioner) defaultExecuteCommand() string {
|
||||
func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
|
||||
|
||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
// Create passthrough for build-generated data
|
||||
p.config.ctx.Data = packer.BasicPlaceholderData()
|
||||
|
||||
err := config.Decode(&p.config, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &p.config.ctx,
|
||||
|
||||
@@ -154,8 +154,6 @@ type EnvVarsTemplate struct {
|
||||
func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
|
||||
|
||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
// Create passthrough for build-generated data
|
||||
p.config.ctx.Data = packer.BasicPlaceholderData()
|
||||
err := config.Decode(&p.config, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &p.config.ctx,
|
||||
|
||||
@@ -148,9 +148,6 @@ type EnvVarsTemplate struct {
|
||||
func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
|
||||
|
||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||
// Create passthrough for build-generated data
|
||||
p.config.ctx.Data = packer.BasicPlaceholderData()
|
||||
|
||||
err := config.Decode(&p.config, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &p.config.ctx,
|
||||
|
||||
+2
-1
@@ -39,6 +39,8 @@ for PLATFORM in $(find ./pkg -mindepth 1 -maxdepth 1 -type d); do
|
||||
popd >/dev/null 2>&1
|
||||
done
|
||||
|
||||
./scripts/sign.sh
|
||||
|
||||
if [ -z $NOSIGN ]; then
|
||||
echo "==> Signing..."
|
||||
pushd ./pkg/dist
|
||||
@@ -48,7 +50,6 @@ if [ -z $NOSIGN ]; then
|
||||
popd
|
||||
fi
|
||||
|
||||
./scripts/sign.sh
|
||||
hc-releases upload $DIR/pkg/dist/
|
||||
hc-releases publish
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import (
|
||||
var GitCommit string
|
||||
|
||||
// The main version number that is being run at the moment.
|
||||
const Version = "1.5.0"
|
||||
const Version = "1.5.1"
|
||||
|
||||
// A pre-release marker for the version. If this is "" (empty string)
|
||||
// then it means that it is a final release. Otherwise, this is a pre-release
|
||||
|
||||
@@ -112,7 +112,7 @@ GEM
|
||||
tilt (>= 1.4.1, < 3)
|
||||
padrino-support (0.12.9)
|
||||
activesupport (>= 3.1)
|
||||
rack (1.6.11)
|
||||
rack (1.6.12)
|
||||
rack-livereload (0.3.17)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ set :base_url, "https://www.packer.io/"
|
||||
|
||||
activate :hashicorp do |h|
|
||||
h.name = "packer"
|
||||
h.version = "1.5.0"
|
||||
h.version = "1.5.1"
|
||||
h.github_slug = "hashicorp/packer"
|
||||
h.website_root = "website"
|
||||
end
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
---
|
||||
layout: "docs"
|
||||
page_title: "Expressions - Configuration Language"
|
||||
sidebar_current: configuration-expressions
|
||||
description: |-
|
||||
HCL allows the use of expressions to access data exported
|
||||
by resources and to transform and combine that data to produce other values.
|
||||
---
|
||||
|
||||
# Expressions
|
||||
|
||||
_Expressions_ are used to refer to or compute values within a configuration.
|
||||
The simplest expressions are just literal values, like `"hello"` or `5`, but
|
||||
HCL also allows more complex expressions such as references to data exported by
|
||||
resources, arithmetic, conditional evaluation, and a number of built-in
|
||||
functions.
|
||||
|
||||
Expressions can be used in a number of places in HCL, but some contexts limit
|
||||
which expression constructs are allowed, such as requiring a literal value of a
|
||||
particular type or forbidding. Each language feature's documentation describes
|
||||
any restrictions it places on expressions.
|
||||
|
||||
The rest of this page describes all of the features of Packer's
|
||||
expression syntax.
|
||||
|
||||
## Types and Values
|
||||
|
||||
The result of an expression is a _value_. All values have a _type_, which
|
||||
dictates where that value can be used and what transformations can be
|
||||
applied to it.
|
||||
|
||||
HCL uses the following types for its values:
|
||||
|
||||
* `string`: a sequence of Unicode characters representing some text, like
|
||||
`"hello"`.
|
||||
* `number`: a numeric value. The `number` type can represent both whole
|
||||
numbers like `15` and fractional values like `6.283185`.
|
||||
* `bool`: either `true` or `false`. `bool` values can be used in conditional
|
||||
logic.
|
||||
* `list` (or `tuple`): a sequence of values, like
|
||||
`["us-west-1a", "us-west-1c"]`. Elements in a list or tuple are identified by
|
||||
consecutive whole numbers, starting with zero.
|
||||
* `map` (or `object`): a group of values identified by named labels, like
|
||||
`{name = "Mabel", age = 52}`.
|
||||
|
||||
Strings, numbers, and bools are sometimes called _primitive types._
|
||||
Lists/tuples and maps/objects are sometimes called _complex types,_ _structural
|
||||
types,_ or _collection types._
|
||||
|
||||
Finally, there is one special value that has _no_ type:
|
||||
|
||||
* `null`: a value that represents _absence_ or _omission._ If you set an
|
||||
argument of a source or module to `null`, Packer behaves as though you
|
||||
had completely omitted it — it will use the argument's default value if it has
|
||||
one, or raise an error if the argument is mandatory. `null` is most useful in
|
||||
conditional expressions, so you can dynamically omit an argument if a
|
||||
condition isn't met.
|
||||
|
||||
### Advanced Type Details
|
||||
|
||||
In most situations, lists and tuples behave identically, as do maps and objects.
|
||||
Whenever the distinction isn't relevant, the Packer documentation uses each
|
||||
pair of terms interchangeably (with a historical preference for "list" and
|
||||
"map").
|
||||
|
||||
However, module authors and provider developers should understand the
|
||||
differences between these similar types (and the related `set` type), since they
|
||||
offer different ways to restrict the allowed values for input variables and
|
||||
source arguments.
|
||||
|
||||
### Type Conversion
|
||||
|
||||
Expressions are most often used to set values for the arguments of resources and
|
||||
child modules. In these cases, the argument has an expected type and the given
|
||||
expression must produce a value of that type.
|
||||
|
||||
Where possible, Packer automatically converts values from one type to
|
||||
another in order to produce the expected type. If this isn't possible, Packer
|
||||
will produce a type mismatch error and you must update the configuration with a
|
||||
more suitable expression.
|
||||
|
||||
Packer automatically converts number and bool values to strings when needed.
|
||||
It also converts strings to numbers or bools, as long as the string contains a
|
||||
valid representation of a number or bool value.
|
||||
|
||||
* `true` converts to `"true"`, and vice-versa
|
||||
* `false` converts to `"false"`, and vice-versa
|
||||
* `15` converts to `"15"`, and vice-versa
|
||||
|
||||
## Literal Expressions
|
||||
|
||||
A _literal expression_ is an expression that directly represents a particular
|
||||
constant value. Packer has a literal expression syntax for each of the value
|
||||
types described above:
|
||||
|
||||
* Strings are usually represented by a double-quoted sequence of Unicode
|
||||
characters, `"like this"`. There is also a "heredoc" syntax for more complex
|
||||
strings. String literals are the most complex kind of literal expression in
|
||||
Packer, and have additional documentation on this page:
|
||||
* See [String Literals](#string-literals) below for information about escape
|
||||
sequences and the heredoc syntax.
|
||||
* See [String Templates](#string-templates) below for information about
|
||||
interpolation and template directives.
|
||||
* Numbers are represented by unquoted sequences of digits with or without a
|
||||
decimal point, like `15` or `6.283185`.
|
||||
* Bools are represented by the unquoted symbols `true` and `false`.
|
||||
* The null value is represented by the unquoted symbol `null`.
|
||||
* Lists/tuples are represented by a pair of square brackets containing a
|
||||
comma-separated sequence of values, like `["a", 15, true]`.
|
||||
|
||||
List literals can be split into multiple lines for readability, but always
|
||||
require a comma between values. A comma after the final value is allowed,
|
||||
but not required. Values in a list can be arbitrary expressions.
|
||||
* Maps/objects are represented by a pair of curly braces containing a series of
|
||||
`<KEY> = <VALUE>` pairs:
|
||||
|
||||
```hcl
|
||||
{
|
||||
name = "John"
|
||||
age = 52
|
||||
}
|
||||
```
|
||||
|
||||
Key/value pairs can be separated by either a comma or a line break. Values
|
||||
can be arbitrary expressions. Keys are strings; they can be left unquoted if
|
||||
they are a valid [identifier](./syntax.html#identifiers), but must be quoted
|
||||
otherwise. You can use a non-literal expression as a key by wrapping it in
|
||||
parentheses, like `(var.business_unit_tag_name) = "SRE"`.
|
||||
|
||||
## References to Named Values
|
||||
|
||||
Packer makes one named values available.
|
||||
|
||||
The following named values are available:
|
||||
|
||||
* `source.<SOURCE TYPE>.<NAME>` is an object representing a
|
||||
[source](./sources.html) of the given type
|
||||
and name.
|
||||
|
||||
## String Literals
|
||||
|
||||
HCL has two different syntaxes for string literals. The
|
||||
most common is to delimit the string with quote characters (`"`), like
|
||||
`"hello"`. In quoted strings, the backslash character serves as an escape
|
||||
sequence, with the following characters selecting the escape behavior:
|
||||
|
||||
| Sequence | Replacement |
|
||||
| ------------ | ----------------------------------------------------------------------------- |
|
||||
| `\n` | Newline |
|
||||
| `\r` | Carriage Return |
|
||||
| `\t` | Tab |
|
||||
| `\"` | Literal quote (without terminating the string) |
|
||||
| `\\` | Literal backslash |
|
||||
| `\uNNNN` | Unicode character from the basic multilingual plane (NNNN is four hex digits) |
|
||||
| `\UNNNNNNNN` | Unicode character from supplementary planes (NNNNNNNN is eight hex digits) |
|
||||
|
||||
The alternative syntax for string literals is the so-called Here Documents or
|
||||
"heredoc" style, inspired by Unix shell languages. This style allows multi-line
|
||||
strings to be expressed more clearly by using a custom delimiter word on a line
|
||||
of its own to close the string:
|
||||
|
||||
```hcl
|
||||
<<EOF
|
||||
hello
|
||||
world
|
||||
EOF
|
||||
```
|
||||
|
||||
The `<<` marker followed by any identifier at the end of a line introduces the
|
||||
sequence. Packer then processes the following lines until it finds one that
|
||||
consists entirely of the identifier given in the introducer. In the above
|
||||
example, `EOF` is the identifier selected. Any identifier is allowed, but
|
||||
conventionally this identifier is in all-uppercase and begins with `EO`, meaning
|
||||
"end of". `EOF` in this case stands for "end of text".
|
||||
|
||||
The "heredoc" form shown above requires that the lines following be flush with
|
||||
the left margin, which can be awkward when an expression is inside an indented
|
||||
block:
|
||||
|
||||
```hcl
|
||||
block {
|
||||
value = <<EOF
|
||||
hello
|
||||
world
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
To improve on this, Packer also accepts an _indented_ heredoc string variant
|
||||
that is introduced by the `<<-` sequence:
|
||||
|
||||
```hcl
|
||||
block {
|
||||
value = <<-EOF
|
||||
hello
|
||||
world
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
In this case, Packer analyses the lines in the sequence to find the one
|
||||
with the smallest number of leading spaces, and then trims that many spaces
|
||||
from the beginning of all of the lines, leading to the following result:
|
||||
|
||||
```
|
||||
hello
|
||||
world
|
||||
```
|
||||
|
||||
Backslash sequences are not interpreted in a heredoc string expression.
|
||||
Instead, the backslash character is interpreted literally.
|
||||
|
||||
In both quoted and heredoc string expressions, Packer supports template
|
||||
sequences that begin with `${` and `%{`. These are described in more detail
|
||||
in the following section. To include these sequences _literally_ without
|
||||
beginning a template sequence, double the leading character: `$${` or `%%{`.
|
||||
|
||||
## String Templates
|
||||
|
||||
Within quoted and heredoc string expressions, the sequences `${` and `%{` begin
|
||||
_template sequences_. Templates let you directly embed expressions into a string
|
||||
literal, to dynamically construct strings from other values.
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
layout: "docs"
|
||||
page_title: "Configuration Language"
|
||||
sidebar_current: "configuration"
|
||||
description: |-
|
||||
Packer uses text files to describe infrastructure and to set variables.
|
||||
These text files are called Packer _configurations_ and are
|
||||
written in the HCL language.
|
||||
---
|
||||
|
||||
# HCL Configuration Language
|
||||
|
||||
Packer uses the Hashicorp Configuration Language - HCL - designed to allow
|
||||
concise descriptions of the required steps to get to a build file. This page
|
||||
describes the features of HCL2 exhaustively, if you would like to give a quick
|
||||
try to HCL2, you can also read the quicker [HCL2 getting started
|
||||
guide](/guides/hcl).
|
||||
|
||||
## Builds
|
||||
|
||||
The main purpose of the HCL language is defining builds and sources. All other
|
||||
language features exist only to make the definition of builds more flexible and
|
||||
convenient.
|
||||
|
||||
|
||||
`packer build` takes one argument. When a directory is passed, all files in the
|
||||
folder with a name ending with ".pkr.hcl" or ".pkr.json" will be parsed using
|
||||
the HCL2 format. When a file ending with ".pkr.hcl" or ".pkr.json" is passed it
|
||||
will be parsed using the HCL2 schema. For every other case; the *JSON only* old
|
||||
packer schema will be used.
|
||||
|
||||
## Arguments, Blocks, and Expressions
|
||||
|
||||
The syntax of the HCL language consists of only a few basic elements:
|
||||
|
||||
```hcl
|
||||
source "amazon-ebs" "main" {
|
||||
ami_name = "main-ami"
|
||||
}
|
||||
|
||||
<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
|
||||
# Block body
|
||||
<IDENTIFIER> = <EXPRESSION> # Argument
|
||||
}
|
||||
```
|
||||
|
||||
- _Blocks_ are containers for other content and usually represent the
|
||||
configuration of some kind of object, like a source. Blocks have a
|
||||
_block type,_ can have zero or more _labels,_ and have a _body_ that contains
|
||||
any number of arguments and nested blocks. Most of Packer's features are
|
||||
controlled by top-level blocks in a configuration file.
|
||||
- _Arguments_ assign a value to a name. They appear within blocks.
|
||||
- _Expressions_ represent a value, either literally or by referencing and
|
||||
combining other values. They appear as values for arguments, or within other
|
||||
expressions.
|
||||
|
||||
For full details about Packer's syntax, see:
|
||||
|
||||
- [Configuration Syntax](./syntax.html)
|
||||
- [Expressions](./expressions.html)
|
||||
|
||||
## Code Organization
|
||||
|
||||
The HCL language uses configuration files that are named with the `.pkr.hcl`
|
||||
file extension. There is also [a JSON-based variant of the
|
||||
language](./syntax-json.html) that is named with the `.pkr.json` file
|
||||
extension.
|
||||
|
||||
Configuration files must always use UTF-8 encoding, and by convention are
|
||||
usually maintained with Unix-style line endings (LF) rather than Windows-style
|
||||
line endings (CRLF), though both are accepted.
|
||||
|
||||
## Configuration Ordering
|
||||
|
||||
The ordering of root blocks is not significant. The order of `provisioner` or
|
||||
`post-processor` blocks within a `build` is the only major feature where block
|
||||
order matters.
|
||||
@@ -0,0 +1,276 @@
|
||||
---
|
||||
layout: "docs"
|
||||
page_title: "JSON Configuration Syntax - Configuration Language"
|
||||
sidebar_current: configuration-json-syntax
|
||||
description: |-
|
||||
In addition to the native syntax that is most commonly used with Packer,
|
||||
the HCL language can also be expressed in a JSON-compatible syntax.
|
||||
---
|
||||
|
||||
# JSON Configuration Syntax
|
||||
|
||||
|
||||
Most Packer configurations are written in [the native HCL
|
||||
syntax](./syntax.html), which is designed to be easy for humans to read and
|
||||
update.
|
||||
|
||||
Packer also supports an alternative syntax that is JSON-compatible. This
|
||||
syntax is useful when generating portions of a configuration programmatically,
|
||||
since existing JSON libraries can be used to prepare the generated
|
||||
configuration files.
|
||||
|
||||
The JSON syntax is defined in terms of the native syntax. Everything that can
|
||||
be expressed in native syntax can also be expressed in JSON syntax, but some
|
||||
constructs are more complex to represent in JSON due to limitations of the
|
||||
JSON grammar.
|
||||
|
||||
Packer expects native syntax for files named with a `.pkr.hcl` suffix, and JSON
|
||||
syntax for files named with a `.pkr.json` suffix.
|
||||
|
||||
The low-level JSON syntax, just as with the native syntax, is defined in terms
|
||||
of a specification called _HCL_. It is not necessary to know all of the details
|
||||
of HCL syntax or its JSON mapping in order to use Packer, and so this page
|
||||
summarizes the most important differences between native and JSON syntax. If
|
||||
you are interested, you can find a full definition of HCL's JSON syntax in [its
|
||||
specification](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md).
|
||||
|
||||
## JSON File Structure
|
||||
|
||||
At the root of any JSON-based Packer configuration is a JSON object. The
|
||||
properties of this object correspond to the top-level block types of the
|
||||
Packer language. For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"variables": {
|
||||
"example": "value"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each top-level object property must match the name of one of the expected
|
||||
top-level block types. Block types that expect labels, such as `variable` shown
|
||||
above, are represented by one nested object value for each level of label.
|
||||
`source` blocks expect two labels, so two levels of nesting are required:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"amazon-ebs": {
|
||||
"example": {
|
||||
"instance_type": "t2.micro",
|
||||
"ami_name": "ami-abc123"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After any nested objects representing the labels, finally one more nested
|
||||
object represents the body of the block itself. In the above example the
|
||||
`instance_type` and `ami_name` arguments for `source "amazon-ebs" "example"`
|
||||
are specified.
|
||||
|
||||
Taken together, the above two configuration files are equivalent to the
|
||||
following blocks in the native syntax:
|
||||
|
||||
```hcl
|
||||
variables {
|
||||
example = "value"
|
||||
}
|
||||
|
||||
source "amazon-ebs" "example" {
|
||||
instance_type = "t2.micro"
|
||||
ami_name = "ami-abc123"
|
||||
}
|
||||
```
|
||||
|
||||
Within each top-level block type the rules for mapping to JSON are slightly
|
||||
different (see [Block-type-specific Exceptions][inpage-exceptions] below), but the following general rules apply in most cases:
|
||||
|
||||
* The JSON object representing the block body contains properties that
|
||||
correspond either to argument names or to nested block type names.
|
||||
|
||||
* Where a property corresponds to an argument that accepts
|
||||
[arbitrary expressions](./expressions.html) in the native syntax, the
|
||||
property value is mapped to an expression as described under
|
||||
[_Expression Mapping_](#expression-mapping) below. For arguments that
|
||||
do _not_ accept arbitrary expressions, the interpretation of the property
|
||||
value depends on the argument, as described in the
|
||||
[block-type-specific exceptions](#block-type-specific-exceptions)
|
||||
given later in this page.
|
||||
|
||||
* Where a property name corresponds to an expected nested block type name,
|
||||
the value is interpreted as described under
|
||||
[_Nested Block Mapping_](#nested-block-mapping) below, unless otherwise
|
||||
stated in [the block-type-specific exceptions](#block-type-specific-exceptions)
|
||||
given later in this page.
|
||||
|
||||
## Expression Mapping
|
||||
|
||||
Since JSON grammar is not able to represent all of the Packer language
|
||||
[expression syntax](./expressions.html), JSON values interpreted as expressions
|
||||
are mapped as follows:
|
||||
|
||||
| JSON | Packer Language Interpretation |
|
||||
| ------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| Boolean | A literal `bool` value. |
|
||||
| Number | A literal `number` value. |
|
||||
| String | Parsed as a [string template](./expressions.html#string-templates) and then evaluated as described below. |
|
||||
| Object | Each property value is mapped per this table, producing an `object(...)` value with suitable attribute types. |
|
||||
| Array | Each element is mapped per this table, producing a `tuple(...)` value with suitable element types. |
|
||||
| Null | A literal `null`. |
|
||||
|
||||
When a JSON string is encountered in a location where arbitrary expressions are
|
||||
expected, its value is first parsed as a [string template](./expressions.html#string-templates)
|
||||
and then it is evaluated to produce the final result.
|
||||
|
||||
If the given template consists _only_ of a single interpolation sequence,
|
||||
the result of its expression is taken directly, without first converting it
|
||||
to a string. This allows non-string expressions to be used within the
|
||||
JSON syntax.
|
||||
|
||||
## Nested Block Mapping
|
||||
|
||||
When a JSON object property is named after a nested block type, the value
|
||||
of this property represents one or more blocks of that type. The value of
|
||||
the property must be either a JSON object or a JSON array.
|
||||
|
||||
The simplest situation is representing only a single block of the given type
|
||||
when that type expects no labels, as with the `tags` nested block used
|
||||
within `source` blocks:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"amazon-ebs": {
|
||||
"example": {
|
||||
"tags": {
|
||||
"key": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The above is equivalent to the following native syntax configuration:
|
||||
|
||||
```hcl
|
||||
source "amazon-ebs" "example" {
|
||||
tags {
|
||||
key = "value"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When the nested block type requires one or more labels, or when multiple
|
||||
blocks of the same type can be given, the mapping gets a little more
|
||||
complicated. For example, the `provisioner` nested block type used
|
||||
within `source` blocks expects a label giving the provisioner to use,
|
||||
and the ordering of provisioner blocks is significant to decide the order
|
||||
of operations.
|
||||
|
||||
The following native syntax example shows a `source` block with a number
|
||||
of provisioners of different types:
|
||||
|
||||
```hcl
|
||||
source "amazon-ebs" "example" {
|
||||
# (source configuration omitted for brevity)
|
||||
|
||||
provisioner "shell-local" {
|
||||
inline = ["echo 'Hello World' >example.txt"]
|
||||
}
|
||||
provisioner "file" {
|
||||
source = "example.txt"
|
||||
destination = "/tmp/example.txt"
|
||||
}
|
||||
provisioner "shell" {
|
||||
inline = [
|
||||
"sudo install-something -f /tmp/example.txt",
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In order to preserve the order of these blocks, you must use a JSON array
|
||||
as the direct value of the property representing this block type, as in
|
||||
this JSON equivalent of the above:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"amazon-ebs": {
|
||||
"example": {
|
||||
"provisioner": [
|
||||
{
|
||||
"shell-local": {
|
||||
"inline": ["echo 'Hello World' >example.txt"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": {
|
||||
"source": "example.txt",
|
||||
"destination": "/tmp/example.txt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"shell": {
|
||||
"inline": ["sudo install-something -f /tmp/example.txt"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each element of the `provisioner` array is an object with a single property
|
||||
whose name represents the label for each `provisioner` block. For block types
|
||||
that expect multiple labels, this pattern of alternating array and object
|
||||
nesting can be used for each additional level.
|
||||
|
||||
If a nested block type requires labels but the order does _not_ matter, you
|
||||
may omit the array and provide just a single object whose property names
|
||||
correspond to unique block labels. This is allowed as a shorthand for the above
|
||||
for simple cases, but the alternating array and object approach is the most
|
||||
general. We recommend using the most general form if systematically converting
|
||||
from native syntax to JSON, to ensure that the meaning of the configuration is
|
||||
preserved exactly.
|
||||
|
||||
### Comment Properties
|
||||
|
||||
Although we do not recommend hand-editing of JSON syntax configuration files
|
||||
-- this format is primarily intended for programmatic generation and consumption --
|
||||
a limited form of _comments_ are allowed inside JSON objects that represent
|
||||
block bodies using a special property name:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": {
|
||||
"amazon-ebs": {
|
||||
"example": {
|
||||
"//": "This instance runs the scheduled tasks for backup",
|
||||
|
||||
"instance_type": "t2.micro",
|
||||
"ami_name": "ami-abc123"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In any object that represents a block body, properties named `"//"` are
|
||||
ignored by Packer entirely. This exception does _not_ apply to objects
|
||||
that are being [interpreted as expressions](#expression-mapping), where this
|
||||
would be interpreted as an object type attribute named `"//"`.
|
||||
|
||||
This special property name can also be used at the root of a JSON-based
|
||||
configuration file. This can be useful to note which program created the file.
|
||||
|
||||
```json
|
||||
{
|
||||
"//": "This file is generated by generate-outputs.py. DO NOT HAND-EDIT!",
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,119 @@
|
||||
---
|
||||
layout: "docs"
|
||||
page_title: "Syntax - Configuration Language"
|
||||
sidebar_current: configuration-syntax
|
||||
description: |-
|
||||
HCL has its own syntax, intended to combine declarative
|
||||
structure with expressions in a way that is easy for humans to read and
|
||||
understand.
|
||||
---
|
||||
|
||||
# HCL Configuration Syntax
|
||||
|
||||
Other pages in this section have described various configuration constructs
|
||||
that can appear in HCL. This page describes the lower-level syntax of the
|
||||
language in more detail, revealing the building blocks that those constructs
|
||||
are built from.
|
||||
|
||||
This page describes the _native syntax_ of HCL, which is a rich language
|
||||
designed to be easy for humans to read and write. The constructs in HCL can
|
||||
also be expressed in [JSON syntax](./syntax-json.html), which is harder for
|
||||
humans to read and edit but easier to generate and parse programmatically.
|
||||
|
||||
This low-level syntax of HCL is defined in terms of a syntax called _HCL_,
|
||||
which is also used by configuration languages in other applications, and in
|
||||
particular other HashiCorp products. It is not necessary to know all of the
|
||||
details of HCL in order to use Packer, and so this page summarizes the most
|
||||
important details. If you are interested, you can find a full definition of HCL
|
||||
syntax in [the HCL native syntax
|
||||
specification](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md).
|
||||
|
||||
## Arguments and Blocks
|
||||
|
||||
HCL syntax is built around two key syntax constructs:
|
||||
arguments and blocks.
|
||||
|
||||
### Arguments
|
||||
|
||||
An _argument_ assigns a value to a particular name:
|
||||
|
||||
```hcl
|
||||
image_id = "abc123"
|
||||
```
|
||||
|
||||
The identifier before the equals sign is the _argument name_, and the expression
|
||||
after the equals sign is the argument's value.
|
||||
|
||||
The context where the argument appears determines what value types are valid
|
||||
(for example, each source type has a schema that defines the types of its
|
||||
arguments), but many arguments accept arbitrary
|
||||
[expressions](./expressions.html), which allow the value to
|
||||
either be specified literally or generated from other values programmatically.
|
||||
|
||||
### Blocks
|
||||
|
||||
A _block_ is a container for other content:
|
||||
|
||||
```hcl
|
||||
source "amazon-ebs" "example" {
|
||||
ami_name = "abc123"
|
||||
|
||||
tags {
|
||||
# ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A block has a _type_ (`source` in this example). Each block type defines
|
||||
how many _labels_ must follow the type keyword. The `source` block type
|
||||
expects two labels, which are `amazon-ebs` and `example` in the example above.
|
||||
A particular block type may have any number of required labels, or it may
|
||||
require none as with the nested `tags` block type.
|
||||
|
||||
After the block type keyword and any labels, the block _body_ is delimited
|
||||
by the `{` and `}` characters. Within the block body, further arguments
|
||||
and blocks may be nested, creating a hierarchy of blocks and their associated
|
||||
arguments.
|
||||
|
||||
HCL uses a limited number of _top-level block types,_ which
|
||||
are blocks that can appear outside of any other block in a configuration file.
|
||||
Most of Packer's features (including resources, input variables, output
|
||||
values, data sources, etc.) are implemented as top-level blocks.
|
||||
|
||||
## Identifiers
|
||||
|
||||
Argument names, block type names, and the names of most Packer-specific
|
||||
constructs like resources, input variables, etc. are all _identifiers_.
|
||||
|
||||
Identifiers can contain letters, digits, underscores (`_`), and hyphens (`-`).
|
||||
The first character of an identifier must not be a digit, to avoid ambiguity
|
||||
with literal numbers.
|
||||
|
||||
For complete identifier rules, Packer implements
|
||||
[the Unicode identifier syntax](http://unicode.org/reports/tr31/), extended to
|
||||
include the ASCII hyphen character `-`.
|
||||
|
||||
## Comments
|
||||
|
||||
HCL supports three different syntaxes for comments:
|
||||
|
||||
* `#` begins a single-line comment, ending at the end of the line.
|
||||
* `//` also begins a single-line comment, as an alternative to `#`.
|
||||
* `/*` and `*/` are start and end delimiters for a comment that might span
|
||||
over multiple lines.
|
||||
|
||||
The `#` single-line comment style is the default comment style and should be
|
||||
used in most cases. Automatic configuration formatting tools may automatically
|
||||
transform `//` comments into `#` comments, since the double-slash style is
|
||||
not idiomatic.
|
||||
|
||||
## Character Encoding and Line Endings
|
||||
|
||||
Packer configuration files must always be UTF-8 encoded. While the
|
||||
delimiters of the language are all ASCII characters, Packer accepts
|
||||
non-ASCII characters in identifiers, comments, and string values.
|
||||
|
||||
Packer accepts configuration files with either Unix-style line endings
|
||||
(LF only) or Windows-style line endings (CR then LF), but the idiomatic style
|
||||
is to use the Unix convention, and so automatic configuration formatting tools
|
||||
may automatically transform CRLF endings to LF.
|
||||
@@ -31,7 +31,8 @@ method should do.
|
||||
|
||||
``` go
|
||||
type Builder interface {
|
||||
Prepare(...interface{}) error
|
||||
ConfigSpec() hcldec.ObjectSpec
|
||||
Prepare(...interface{}) ([]string, []string, error)
|
||||
Run(context.Context, ui Ui, hook Hook) (Artifact, error)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -36,6 +36,7 @@ explaining what each method should do.
|
||||
|
||||
``` go
|
||||
type PostProcessor interface {
|
||||
ConfigSpec() hcldec.ObjectSpec
|
||||
Configure(interface{}) error
|
||||
PostProcess(context.Context, Ui, Artifact) (a Artifact, keep, mustKeep bool, err error)
|
||||
}
|
||||
|
||||
@@ -35,8 +35,9 @@ explaining what each method should do.
|
||||
|
||||
``` go
|
||||
type Provisioner interface {
|
||||
ConfigSpec() hcldec.ObjectSpec
|
||||
Prepare(...interface{}) error
|
||||
Provision(Ctx, Ui, Communicator, new(interface{})) error
|
||||
Provision(context.Context, Ui, Communicator, map[string]interface{}) error
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+6
-4
@@ -72,9 +72,9 @@ Here is a full list of the available functions for reference.
|
||||
"inline": ["echo $TESTVAR"]
|
||||
},
|
||||
```
|
||||
Valid variables to request are: "InstanceID", "CommunicatorHost",
|
||||
"CommunicatorPort", "CommunicatorUser", "CommunicatorPassword", "ConnType",
|
||||
"PackerRunUUID", "CommunicatorPublicKey", and "CommunicatorPrivateKey".
|
||||
Valid variables to request are: "ID", "Host",
|
||||
"Port", "User", "Password", "ConnType",
|
||||
"PackerRunUUID", "SSHPublicKey", and "SSHPrivateKey".
|
||||
Depending on which communicator you are using, some of these values may be
|
||||
empty -- for example, the public and private keys are unique to the SSH
|
||||
communicator. InstanceID represents the vm being provisioned. For example,
|
||||
@@ -84,7 +84,9 @@ Here is a full list of the available functions for reference.
|
||||
For backwards compatability, `WinRMPassword` is also available through this
|
||||
engine, though it is no different than using the more general `Password`.
|
||||
|
||||
This function is only for use within _provisioners_, and does not yet work
|
||||
This function is only for use within specific options inside of
|
||||
_provisioners_ -- these options will be listed as being template engines
|
||||
in the provisioner documentation. This feature does not yet work
|
||||
if the provisioners are being used in conjunction with our chroot builders
|
||||
or with lxc/lxd builders.
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
layout: guides
|
||||
page_title: Generating code for config spec.
|
||||
sidebar_current: hcl-component-object-spec
|
||||
description: |-
|
||||
Learn how to generate the HCL2 configuration of your component easily.
|
||||
---
|
||||
|
||||
# Auto Generate the HCL2 code of a plugin
|
||||
|
||||
From v1.5, Packer can be configured using HCL2. Because Packer has so many
|
||||
builders, provisioner & post-processors, we relied on code generation to
|
||||
iterate more easily. The good new is that you can benefit from this code
|
||||
generator to get the HCL2 spec code of your component simply. It's a Go binary
|
||||
package and is located in [`cmd/mapstructure-to-hcl2`](https://github.com/hashicorp/packer/tree/master/cmd/mapstructure-to-hcl2).
|
||||
|
||||
Say you want to configure the `Config` struct of a `Builder` in a package
|
||||
located in `my/example-plugin/config.go`. Here are some simple steps you can
|
||||
follow to make it HCL2 enabled:
|
||||
|
||||
* run `go install github.com/hashicorp/packer/cmd/mapstructure-to-hcl2`
|
||||
|
||||
* Add `//go:generate mapstructure-to-hcl2 -type Config` at the top of
|
||||
`config.go`
|
||||
|
||||
* run `go generate ./my/example-plugin/...`
|
||||
|
||||
This will generate a `my/example-plugin/config.hcl2spec.go` file containing
|
||||
the configuration fields of `Config`.
|
||||
|
||||
* Make sure that all the nested structs of `Config` are also auto generated the
|
||||
same way.
|
||||
|
||||
* Now we only need to make Builder implement the interface by adding the
|
||||
following snippet:
|
||||
|
||||
```go
|
||||
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
|
||||
```
|
||||
|
||||
From now on every time you add or change a field of Config you will need to
|
||||
run the `go generate` command again.
|
||||
|
||||
A good example of this is the [Config struct of the amazon-ebs builder](https://github.com/hashicorp/packer/blob/master/builder/amazon/ebs/builder.go)
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
layout: guides
|
||||
page_title: Transforming Packer v1 files for Packer v1.5.0
|
||||
sidebar_current: hcl
|
||||
sidebar_current: hcl-from-json-v1
|
||||
description: |-
|
||||
Learn how to manually move from a Packer v1 working JSON build file to a
|
||||
working v1.5.0 HCL file.
|
||||
---
|
||||
|
||||
# Transforming Packer v1 files for Packer v1.5
|
||||
# Transforming Packer v1 config files to HCL2 for Packer v1.5
|
||||
|
||||
-> **Note:** Starting from version **1.5.0** Packer can read HCL2 files.
|
||||
|
||||
|
||||
@@ -50,3 +50,41 @@ It could be super handy for a boot_command.
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
## Building blocks can be split in files
|
||||
|
||||
Currently Packer offers the `source` and the `build` root blocks. These two
|
||||
building blocks can be defined in any order and a `build` can import one or more
|
||||
`source`. Usually a `source` defines what we currently call a builder and a
|
||||
`build` can apply multiple provisioning steps to a source. For example:
|
||||
|
||||
```hcl
|
||||
# folder/sources.pkr.hcl
|
||||
source "amazon-ebs" "example-1" {
|
||||
ami_name = "example-1-ami"
|
||||
}
|
||||
|
||||
source "virtualbox-iso" "example-2" {
|
||||
boot_command = <<EOF
|
||||
<esc><esc><enter><wait>
|
||||
/install/vmlinuz noapic
|
||||
...
|
||||
EOF
|
||||
}
|
||||
```
|
||||
|
||||
```hcl
|
||||
# folder/build.pkr.hcl
|
||||
build {
|
||||
sources = [
|
||||
"source.amazon-ebs.example-1",
|
||||
"source.virtualbox-iso.example-2"
|
||||
]
|
||||
|
||||
provisioner "shell" {
|
||||
inline = [
|
||||
"echo it's alive !"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
<% wrap_layout :inner do %>
|
||||
<% content_for :sidebar do %>
|
||||
<ul class="nav docs-sidenav">
|
||||
<li<%= sidebar_current("docs-install") %>>
|
||||
<a href="/docs/install/index.html">Installing Packer</a>
|
||||
|
||||
<li<%= sidebar_current("configuration") %>>
|
||||
<a href="/docs/configuration/from-1.5/index.html">v1.5 Configuration Language</a>
|
||||
<ul class="nav">
|
||||
<li<%= sidebar_current("configuration-syntax") %>>
|
||||
<a href="/docs/configuration/from-1.5/syntax.html">Syntax</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("configuration-expressions") %>>
|
||||
<a href="/docs/configuration/from-1.5/expressions.html">Expressions</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("configuration-json-syntax") %>>
|
||||
<a href="/docs/configuration/from-1.5/syntax-json.html">JSON Syntax</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<hr>
|
||||
|
||||
<li><a href="/docs/basics/terminology.html">Terminology</a></li>
|
||||
|
||||
<li<%= sidebar_current("docs-commands") %>>
|
||||
@@ -384,6 +399,12 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<li<%= sidebar_current("docs-install") %>>
|
||||
<a href="/docs/install/index.html">Installing Packer</a>
|
||||
</li>
|
||||
|
||||
<hr>
|
||||
|
||||
<li<%= sidebar_current("docs-extending") %>>
|
||||
<a href="/docs/extending/index.html">Extending Packer</a>
|
||||
<ul class="nav">
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
<li<%= sidebar_current("hcl-from-json-v1") %>>
|
||||
<a href="/guides/hcl/from-json-v1">from JSON v1</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("hcl-component-object-spec") %>>
|
||||
<a href="/guides/hcl/component-object-spec">Making a plugin HCL2 enabled</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li<%= sidebar_current("automatic-operating-system-installs") %>>
|
||||
|
||||
+3
@@ -3,6 +3,9 @@
|
||||
- `skip_region_validation` (bool) - The region validation can be skipped if this value is true, the default
|
||||
value is false.
|
||||
|
||||
- `skip_image_validation` (bool) - The image validation can be skipped if this value is true, the default
|
||||
value is false.
|
||||
|
||||
- `security_token` (string) - STS access token, can be set through template or by exporting as
|
||||
environment variable such as `export SECURITY_TOKEN=value`.
|
||||
|
||||
@@ -10,3 +10,5 @@
|
||||
|
||||
- [Vultr builder](https://github.com/vultr/packer-builder-vultr) - A builder
|
||||
for creating [Vultr](https://www.vultr.com/) snapshots.
|
||||
|
||||
- [Huawei Cloud ECS builder](https://github.com/huaweicloud/packer-builder-huaweicloud-ecs) - Plugin for creating [Huawei Cloud ECS](https://www.huaweicloud.com/intl/en-us/) images.
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
use this option with a key pair already configured in the source AMI,
|
||||
leave the `ssh_keypair_name` blank. To associate an existing key pair in
|
||||
AWS with the source instance, set the `ssh_keypair_name` field to the
|
||||
name of the key pair.
|
||||
name of the key pair. The environment variable `SSH_AUTH_SOCK` must be
|
||||
set for this option to work properly.
|
||||
|
||||
- `ssh_disable_agent_forwarding` (bool) - If true, SSH agent forwarding will be disabled. Defaults to `false`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user