diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2db310015..330a5f4ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,8 @@
read more about this[GH-8437]
### FEATURES:
+* HCL2/core: it is now possible to set source fields from the `build` block
+ [GH-9291]
* **New post-processor** Yandex Export [GH-9124]
### IMPROVEMENTS:
@@ -25,6 +27,9 @@
* builder/google: Implement iap proxy for googlecompute [GH-9105]
* builder/googlecompute: Changed default disk size. [GH-9071]
* builder/qemu: add support for using a network bridge [GH-9159]
+* builder/qemu: Added `skip_nat_mapping` option to skip the
+ communicator (SSH or WinRM) automatic port forward and use the guest port directly. [GH-9307]
+* builder/qemu: Replace deprecated `ssh_host_port_min` and `ssh_host_port_max` by `host_port_min` and `host_port_max`. [GH-9307]
* builder/virtualbox: Add `output_filename` config option to allow to set a
custom filename instead of forcing to be the same as vm_name. [GH-9174]
* builder/vsphere: floppy_label Parameter for vsphere-iso Builder [GH-9187]
diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go
index 3e797b0e4..33129af51 100644
--- a/builder/qemu/builder.go
+++ b/builder/qemu/builder.go
@@ -75,7 +75,7 @@ type Config struct {
common.ISOConfig `mapstructure:",squash"`
bootcommand.VNCConfig `mapstructure:",squash"`
shutdowncommand.ShutdownConfig `mapstructure:",squash"`
- Comm communicator.Config `mapstructure:",squash"`
+ CommConfig CommConfig `mapstructure:",squash"`
common.FloppyConfig `mapstructure:",squash"`
// Use iso from provided url. Qemu must support
// curl block device. This defaults to `false`.
@@ -288,12 +288,6 @@ type Config struct {
// QMP Socket Path when `qmp_enable` is true. Defaults to
// `output_directory`/`vm_name`.monitor.
QMPSocketPath string `mapstructure:"qmp_socket_path" required:"false"`
- // The minimum and maximum port to use for the SSH port on the host machine
- // which is forwarded to the SSH port on the guest machine. Because Packer
- // often runs in parallel, Packer will choose a randomly available port in
- // this range to use as the host port. By default this is 2222 to 4444.
- SSHHostPortMin int `mapstructure:"ssh_host_port_min" required:"false"`
- SSHHostPortMax int `mapstructure:"ssh_host_port_max" required:"false"`
// If true, do not pass a -display option
// to qemu, allowing it to choose the default. This may be needed when running
// under macOS, and getting errors about sdl not being available.
@@ -425,14 +419,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.CpuCount = 1
}
- if b.config.SSHHostPortMin == 0 {
- b.config.SSHHostPortMin = 2222
- }
-
- if b.config.SSHHostPortMax == 0 {
- b.config.SSHHostPortMax = 4444
- }
-
if b.config.VNCBindAddress == "" {
b.config.VNCBindAddress = "127.0.0.1"
}
@@ -472,9 +458,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
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 {
+ commConfigWarnings, es := b.config.CommConfig.Prepare(&b.config.ctx)
+ if len(es) > 0 {
errs = packer.MultiErrorAppend(errs, es...)
}
+ warnings = append(warnings, commConfigWarnings...)
if !(b.config.Format == "qcow2" || b.config.Format == "raw") {
errs = packer.MultiErrorAppend(
@@ -529,16 +517,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
}
}
- if b.config.SSHHostPortMin > b.config.SSHHostPortMax {
- errs = packer.MultiErrorAppend(
- errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max"))
- }
-
- if b.config.SSHHostPortMin < 0 {
- errs = packer.MultiErrorAppend(
- errs, errors.New("ssh_host_port_min must be positive"))
- }
-
if b.config.VNCPortMin > b.config.VNCPortMax {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max"))
@@ -621,9 +599,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
},
)
- if b.config.Comm.Type != "none" && b.config.NetBridge == "" {
+ if b.config.CommConfig.Comm.Type != "none" && b.config.NetBridge == "" {
steps = append(steps,
- new(stepForwardSSH),
+ new(stepPortForward),
)
}
@@ -636,20 +614,20 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&stepTypeBootCommand{},
)
- if b.config.Comm.Type != "none" && b.config.NetBridge != "" {
+ if b.config.CommConfig.Comm.Type != "none" && b.config.NetBridge != "" {
steps = append(steps,
&stepWaitGuestAddress{
- timeout: b.config.Comm.SSHTimeout,
+ timeout: b.config.CommConfig.Comm.SSHTimeout,
},
)
}
- if b.config.Comm.Type != "none" {
+ if b.config.CommConfig.Comm.Type != "none" {
steps = append(steps,
&communicator.StepConnect{
- Config: &b.config.Comm,
- Host: commHost(b.config.Comm.Host()),
- SSHConfig: b.config.Comm.SSHConfigFunc(),
+ Config: &b.config.CommConfig.Comm,
+ Host: commHost(b.config.CommConfig.Comm.Host()),
+ SSHConfig: b.config.CommConfig.Comm.SSHConfigFunc(),
SSHPort: commPort,
WinRMPort: commPort,
},
@@ -662,7 +640,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
steps = append(steps,
&common.StepCleanupTempKeys{
- Comm: &b.config.Comm,
+ Comm: &b.config.CommConfig.Comm,
},
)
steps = append(steps,
diff --git a/builder/qemu/builder.hcl2spec.go b/builder/qemu/builder.hcl2spec.go
index a0d6ea5d4..0500eecd2 100644
--- a/builder/qemu/builder.hcl2spec.go
+++ b/builder/qemu/builder.hcl2spec.go
@@ -73,6 +73,11 @@ type FlatConfig struct {
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
+ HostPortMin *int `mapstructure:"host_port_min" required:"false" cty:"host_port_min" hcl:"host_port_min"`
+ HostPortMax *int `mapstructure:"host_port_max" required:"false" cty:"host_port_max" hcl:"host_port_max"`
+ SkipNatMapping *bool `mapstructure:"skip_nat_mapping" required:"false" cty:"skip_nat_mapping" hcl:"skip_nat_mapping"`
+ SSHHostPortMin *int `mapstructure:"ssh_host_port_min" required:"false" cty:"ssh_host_port_min" hcl:"ssh_host_port_min"`
+ SSHHostPortMax *int `mapstructure:"ssh_host_port_max" cty:"ssh_host_port_max" hcl:"ssh_host_port_max"`
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files" hcl:"floppy_files"`
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs" hcl:"floppy_dirs"`
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label" hcl:"floppy_label"`
@@ -100,8 +105,6 @@ type FlatConfig struct {
QemuBinary *string `mapstructure:"qemu_binary" required:"false" cty:"qemu_binary" hcl:"qemu_binary"`
QMPEnable *bool `mapstructure:"qmp_enable" required:"false" cty:"qmp_enable" hcl:"qmp_enable"`
QMPSocketPath *string `mapstructure:"qmp_socket_path" required:"false" cty:"qmp_socket_path" hcl:"qmp_socket_path"`
- SSHHostPortMin *int `mapstructure:"ssh_host_port_min" required:"false" cty:"ssh_host_port_min" hcl:"ssh_host_port_min"`
- SSHHostPortMax *int `mapstructure:"ssh_host_port_max" required:"false" cty:"ssh_host_port_max" hcl:"ssh_host_port_max"`
UseDefaultDisplay *bool `mapstructure:"use_default_display" required:"false" cty:"use_default_display" hcl:"use_default_display"`
Display *string `mapstructure:"display" required:"false" cty:"display" hcl:"display"`
VNCBindAddress *string `mapstructure:"vnc_bind_address" required:"false" cty:"vnc_bind_address" hcl:"vnc_bind_address"`
@@ -188,6 +191,11 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
+ "host_port_min": &hcldec.AttrSpec{Name: "host_port_min", Type: cty.Number, Required: false},
+ "host_port_max": &hcldec.AttrSpec{Name: "host_port_max", Type: cty.Number, Required: false},
+ "skip_nat_mapping": &hcldec.AttrSpec{Name: "skip_nat_mapping", Type: cty.Bool, Required: false},
+ "ssh_host_port_min": &hcldec.AttrSpec{Name: "ssh_host_port_min", Type: cty.Number, Required: false},
+ "ssh_host_port_max": &hcldec.AttrSpec{Name: "ssh_host_port_max", Type: cty.Number, Required: false},
"floppy_files": &hcldec.AttrSpec{Name: "floppy_files", Type: cty.List(cty.String), Required: false},
"floppy_dirs": &hcldec.AttrSpec{Name: "floppy_dirs", Type: cty.List(cty.String), Required: false},
"floppy_label": &hcldec.AttrSpec{Name: "floppy_label", Type: cty.String, Required: false},
@@ -215,8 +223,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"qemu_binary": &hcldec.AttrSpec{Name: "qemu_binary", Type: cty.String, Required: false},
"qmp_enable": &hcldec.AttrSpec{Name: "qmp_enable", Type: cty.Bool, Required: false},
"qmp_socket_path": &hcldec.AttrSpec{Name: "qmp_socket_path", Type: cty.String, Required: false},
- "ssh_host_port_min": &hcldec.AttrSpec{Name: "ssh_host_port_min", Type: cty.Number, Required: false},
- "ssh_host_port_max": &hcldec.AttrSpec{Name: "ssh_host_port_max", Type: cty.Number, Required: false},
"use_default_display": &hcldec.AttrSpec{Name: "use_default_display", Type: cty.Bool, Required: false},
"display": &hcldec.AttrSpec{Name: "display", Type: cty.String, Required: false},
"vnc_bind_address": &hcldec.AttrSpec{Name: "vnc_bind_address", Type: cty.String, Required: false},
diff --git a/builder/qemu/builder_test.go b/builder/qemu/builder_test.go
index 963c121db..3eb243abb 100644
--- a/builder/qemu/builder_test.go
+++ b/builder/qemu/builder_test.go
@@ -74,16 +74,16 @@ func TestBuilderPrepare_Defaults(t *testing.T) {
t.Errorf("bad output dir: %s", b.config.OutputDir)
}
- if b.config.SSHHostPortMin != 2222 {
- t.Errorf("bad min ssh host port: %d", b.config.SSHHostPortMin)
+ if b.config.CommConfig.HostPortMin != 2222 {
+ t.Errorf("bad min ssh host port: %d", b.config.CommConfig.HostPortMin)
}
- if b.config.SSHHostPortMax != 4444 {
- t.Errorf("bad max ssh host port: %d", b.config.SSHHostPortMax)
+ if b.config.CommConfig.HostPortMax != 4444 {
+ t.Errorf("bad max ssh host port: %d", b.config.CommConfig.HostPortMax)
}
- if b.config.Comm.SSHPort != 22 {
- t.Errorf("bad ssh port: %d", b.config.Comm.SSHPort)
+ if b.config.CommConfig.Comm.SSHPort != 22 {
+ t.Errorf("bad ssh port: %d", b.config.CommConfig.Comm.SSHPort)
}
if b.config.VMName != "packer-foo" {
@@ -430,8 +430,8 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
config := testConfig()
// Bad
- config["ssh_host_port_min"] = 1000
- config["ssh_host_port_max"] = 500
+ config["host_port_min"] = 1000
+ config["host_port_max"] = 500
b = Builder{}
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
@@ -442,7 +442,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
}
// Bad
- config["ssh_host_port_min"] = -500
+ config["host_port_min"] = -500
b = Builder{}
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
@@ -453,8 +453,8 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
}
// Good
- config["ssh_host_port_min"] = 500
- config["ssh_host_port_max"] = 1000
+ config["host_port_min"] = 500
+ config["host_port_max"] = 1000
b = Builder{}
_, warns, err = b.Prepare(config)
if len(warns) > 0 {
@@ -628,18 +628,31 @@ func TestBuilderPrepare_VNCPassword(t *testing.T) {
func TestCommConfigPrepare_BackwardsCompatibility(t *testing.T) {
var b Builder
config := testConfig()
+ hostPortMin := 1234
+ hostPortMax := 4321
sshTimeout := 2 * time.Minute
+
config["ssh_wait_timeout"] = sshTimeout
+ config["ssh_host_port_min"] = hostPortMin
+ config["ssh_host_port_max"] = hostPortMax
_, warns, err := b.Prepare(config)
- if len(warns) > 0 {
- t.Fatalf("bad: %#v", warns)
+ if len(warns) == 0 {
+ t.Fatalf("should have deprecation warn")
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
- if b.config.Comm.SSHTimeout != sshTimeout {
- t.Fatalf("SSHTimeout should be %s for backwards compatibility, but it was %s", sshTimeout.String(), b.config.Comm.SSHTimeout.String())
+ if b.config.CommConfig.Comm.SSHTimeout != sshTimeout {
+ t.Fatalf("SSHTimeout should be %s for backwards compatibility, but it was %s", sshTimeout.String(), b.config.CommConfig.Comm.SSHTimeout.String())
+ }
+
+ if b.config.CommConfig.HostPortMin != hostPortMin {
+ t.Fatalf("HostPortMin should be %d for backwards compatibility, but it was %d", hostPortMin, b.config.CommConfig.HostPortMin)
+ }
+
+ if b.config.CommConfig.HostPortMax != hostPortMax {
+ t.Fatalf("HostPortMax should be %d for backwards compatibility, but it was %d", hostPortMax, b.config.CommConfig.HostPortMax)
}
}
diff --git a/builder/qemu/comm_config.go b/builder/qemu/comm_config.go
new file mode 100644
index 000000000..45b68b79a
--- /dev/null
+++ b/builder/qemu/comm_config.go
@@ -0,0 +1,72 @@
+//go:generate struct-markdown
+package qemu
+
+import (
+ "errors"
+
+ "github.com/hashicorp/packer/helper/communicator"
+ "github.com/hashicorp/packer/template/interpolate"
+)
+
+type CommConfig struct {
+ Comm communicator.Config `mapstructure:",squash"`
+ // The minimum port to use for the Communicator port on the host machine which is forwarded
+ // to the SSH or WinRM port on the guest machine. By default this is 2222.
+ HostPortMin int `mapstructure:"host_port_min" required:"false"`
+ // The maximum port to use for the Communicator port on the host machine which is forwarded
+ // to the SSH or WinRM port on the guest machine. Because Packer often runs in parallel,
+ // Packer will choose a randomly available port in this range to use as the
+ // host port. By default this is 4444.
+ HostPortMax int `mapstructure:"host_port_max" required:"false"`
+ // Defaults to false. When enabled, Packer
+ // does not setup forwarded port mapping for communicator (SSH or WinRM) requests and uses ssh_port or winrm_port
+ // on the host to communicate to the virtual machine.
+ SkipNatMapping bool `mapstructure:"skip_nat_mapping" required:"false"`
+
+ // These are deprecated, but we keep them around for backwards compatibility
+ // TODO: remove later
+ SSHHostPortMin int `mapstructure:"ssh_host_port_min" required:"false"`
+ // TODO: remove later
+ SSHHostPortMax int `mapstructure:"ssh_host_port_max"`
+}
+
+func (c *CommConfig) Prepare(ctx *interpolate.Context) (warnings []string, errs []error) {
+
+ // Backwards compatibility
+ if c.SSHHostPortMin != 0 {
+ warnings = append(warnings, "ssh_host_port_min is deprecated and is being replaced by host_port_min. "+
+ "Please, update your template to use host_port_min. In future versions of Packer, inclusion of ssh_host_port_min will error your builds.")
+ c.HostPortMin = c.SSHHostPortMin
+ }
+
+ // Backwards compatibility
+ if c.SSHHostPortMax != 0 {
+ warnings = append(warnings, "ssh_host_port_max is deprecated and is being replaced by host_port_max. "+
+ "Please, update your template to use host_port_max. In future versions of Packer, inclusion of ssh_host_port_max will error your builds.")
+ c.HostPortMax = c.SSHHostPortMax
+ }
+
+ if c.Comm.SSHHost == "" {
+ c.Comm.SSHHost = "127.0.0.1"
+ }
+
+ if c.HostPortMin == 0 {
+ c.HostPortMin = 2222
+ }
+
+ if c.HostPortMax == 0 {
+ c.HostPortMax = 4444
+ }
+
+ errs = c.Comm.Prepare(ctx)
+ if c.HostPortMin > c.HostPortMax {
+ errs = append(errs,
+ errors.New("host_port_min must be less than host_port_max"))
+ }
+
+ if c.HostPortMin < 0 {
+ errs = append(errs, errors.New("host_port_min must be positive"))
+ }
+
+ return
+}
diff --git a/builder/qemu/comm_config_test.go b/builder/qemu/comm_config_test.go
new file mode 100644
index 000000000..4912c7d96
--- /dev/null
+++ b/builder/qemu/comm_config_test.go
@@ -0,0 +1,145 @@
+package qemu
+
+import (
+ "io/ioutil"
+ "os"
+ "testing"
+
+ "github.com/hashicorp/packer/helper/communicator"
+ "github.com/hashicorp/packer/template/interpolate"
+)
+
+func testCommConfig() *CommConfig {
+ return &CommConfig{
+ Comm: communicator.Config{
+ SSH: communicator.SSH{
+ SSHUsername: "foo",
+ },
+ },
+ }
+}
+
+func TestCommConfigPrepare(t *testing.T) {
+ c := testCommConfig()
+ warns, errs := c.Prepare(interpolate.NewContext())
+ if len(errs) > 0 {
+ t.Fatalf("err: %#v", errs)
+ }
+ if len(warns) != 0 {
+ t.Fatal("should not have any warnings")
+ }
+
+ if c.HostPortMin != 2222 {
+ t.Errorf("bad min communicator host port: %d", c.HostPortMin)
+ }
+
+ if c.HostPortMax != 4444 {
+ t.Errorf("bad max communicator host port: %d", c.HostPortMax)
+ }
+
+ if c.Comm.SSHPort != 22 {
+ t.Errorf("bad communicator port: %d", c.Comm.SSHPort)
+ }
+}
+
+func TestCommConfigPrepare_SSHHostPort(t *testing.T) {
+ var c *CommConfig
+ var errs []error
+ var warns []string
+
+ // Bad
+ c = testCommConfig()
+ c.HostPortMin = 1000
+ c.HostPortMax = 500
+ warns, errs = c.Prepare(interpolate.NewContext())
+ if len(errs) == 0 {
+ t.Fatalf("bad: %#v", errs)
+ }
+ if len(warns) != 0 {
+ t.Fatal("should not have any warnings")
+ }
+
+ // Good
+ c = testCommConfig()
+ c.HostPortMin = 50
+ c.HostPortMax = 500
+ warns, errs = c.Prepare(interpolate.NewContext())
+ if len(errs) > 0 {
+ t.Fatalf("should not have error: %s", errs)
+ }
+ if len(warns) != 0 {
+ t.Fatal("should not have any warnings")
+ }
+}
+
+func TestCommConfigPrepare_SSHPrivateKey(t *testing.T) {
+ var c *CommConfig
+ var errs []error
+ var warns []string
+
+ c = testCommConfig()
+ c.Comm.SSHPrivateKeyFile = ""
+ warns, errs = c.Prepare(interpolate.NewContext())
+ if len(errs) > 0 {
+ t.Fatalf("should not have error: %#v", errs)
+ }
+ if len(warns) != 0 {
+ t.Fatal("should not have any warnings")
+ }
+
+ c = testCommConfig()
+ c.Comm.SSHPrivateKeyFile = "/i/dont/exist"
+ warns, errs = c.Prepare(interpolate.NewContext())
+ if len(errs) == 0 {
+ t.Fatal("should have error")
+ }
+ if len(warns) != 0 {
+ t.Fatal("should not have any warnings")
+ }
+
+ // Test bad contents
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ if _, err := tf.Write([]byte("HELLO!")); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ c = testCommConfig()
+ c.Comm.SSHPrivateKeyFile = tf.Name()
+ warns, errs = c.Prepare(interpolate.NewContext())
+ if len(errs) == 0 {
+ t.Fatal("should have error")
+ }
+ if len(warns) != 0 {
+ t.Fatal("should not have any warnings")
+ }
+
+ // Test good contents
+ _, err = tf.Seek(0, 0)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ err = tf.Truncate(0)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ _, err = tf.Write([]byte(testPem))
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ c = testCommConfig()
+ c.Comm.SSHPrivateKeyFile = tf.Name()
+ warns, errs = c.Prepare(interpolate.NewContext())
+ if len(errs) > 0 {
+ t.Fatalf("should not have error: %#v", errs)
+ }
+ if len(warns) != 0 {
+ t.Fatal("should not have any warnings")
+ }
+}
diff --git a/builder/qemu/ssh.go b/builder/qemu/ssh.go
index 8f4ceee5c..d722df9e1 100644
--- a/builder/qemu/ssh.go
+++ b/builder/qemu/ssh.go
@@ -22,9 +22,9 @@ func commHost(host string) func(multistep.StateBag) (string, error) {
}
func commPort(state multistep.StateBag) (int, error) {
- sshHostPort, ok := state.Get("sshHostPort").(int)
+ commHostPort, ok := state.Get("commHostPort").(int)
if !ok {
- sshHostPort = 22
+ commHostPort = 22
}
- return int(sshHostPort), nil
+ return commHostPort, nil
}
diff --git a/builder/qemu/step_forward_ssh.go b/builder/qemu/step_port_forward.go
similarity index 54%
rename from builder/qemu/step_forward_ssh.go
rename to builder/qemu/step_port_forward.go
index a296fb078..e4f24b691 100644
--- a/builder/qemu/step_forward_ssh.go
+++ b/builder/qemu/step_port_forward.go
@@ -10,26 +10,30 @@ import (
"github.com/hashicorp/packer/packer"
)
-// This step adds a NAT port forwarding definition so that SSH is available
+// This step adds a NAT port forwarding definition so that SSH or WinRM is available
// on the guest machine.
-//
-// Uses:
-//
-// Produces:
-type stepForwardSSH struct {
+type stepPortForward struct {
l *net.Listener
}
-func (s *stepForwardSSH) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
+func (s *stepPortForward) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
- log.Printf("Looking for available communicator (SSH, WinRM, etc) port between %d and %d", config.SSHHostPortMin, config.SSHHostPortMax)
+ commHostPort := config.CommConfig.Comm.Port()
+
+ if config.CommConfig.SkipNatMapping {
+ log.Printf("Skipping NAT port forwarding. Using communicator (SSH, WinRM, etc) port %d", commHostPort)
+ state.Put("commHostPort", commHostPort)
+ return multistep.ActionContinue
+ }
+
+ log.Printf("Looking for available communicator (SSH, WinRM, etc) port between %d and %d", config.CommConfig.HostPortMin, config.CommConfig.HostPortMax)
var err error
s.l, err = net.ListenRangeConfig{
Addr: config.VNCBindAddress,
- Min: config.SSHHostPortMin,
- Max: config.SSHHostPortMax,
+ Min: config.CommConfig.HostPortMin,
+ Max: config.CommConfig.HostPortMax,
Network: "tcp",
}.Listen(ctx)
if err != nil {
@@ -39,16 +43,16 @@ func (s *stepForwardSSH) Run(ctx context.Context, state multistep.StateBag) mult
return multistep.ActionHalt
}
s.l.Listener.Close() // free port, but don't unlock lock file
- sshHostPort := s.l.Port
- ui.Say(fmt.Sprintf("Found port for communicator (SSH, WinRM, etc): %d.", sshHostPort))
+ commHostPort = s.l.Port
+ ui.Say(fmt.Sprintf("Found port for communicator (SSH, WinRM, etc): %d.", commHostPort))
// Save the port we're using so that future steps can use it
- state.Put("sshHostPort", sshHostPort)
+ state.Put("commHostPort", commHostPort)
return multistep.ActionContinue
}
-func (s *stepForwardSSH) Cleanup(state multistep.StateBag) {
+func (s *stepPortForward) Cleanup(state multistep.StateBag) {
if s.l != nil {
err := s.l.Close()
if err != nil {
diff --git a/builder/qemu/step_run.go b/builder/qemu/step_run.go
index 900162f4f..10727530e 100644
--- a/builder/qemu/step_run.go
+++ b/builder/qemu/step_run.go
@@ -72,7 +72,7 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error
defaultArgs := make(map[string]interface{})
var deviceArgs []string
var driveArgs []string
- var sshHostPort int
+ var commHostPort int
var vnc string
if !config.VNCUsePassword {
@@ -89,9 +89,9 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error
defaultArgs["-machine"] = fmt.Sprintf("type=%s", config.MachineType)
if config.NetBridge == "" {
- if config.Comm.Type != "none" {
- sshHostPort = state.Get("sshHostPort").(int)
- defaultArgs["-netdev"] = fmt.Sprintf("user,id=user.0,hostfwd=tcp::%v-:%d", sshHostPort, config.Comm.Port())
+ if config.CommConfig.Comm.Type != "none" {
+ commHostPort = state.Get("commHostPort").(int)
+ defaultArgs["-netdev"] = fmt.Sprintf("user,id=user.0,hostfwd=tcp::%v-:%d", commHostPort, config.CommConfig.Comm.Port())
} else {
defaultArgs["-netdev"] = fmt.Sprintf("user,id=user.0")
}
@@ -226,14 +226,14 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error
httpIp := state.Get("http_ip").(string)
httpPort := state.Get("http_port").(int)
ictx := config.ctx
- if config.Comm.Type != "none" {
+ if config.CommConfig.Comm.Type != "none" {
ictx.Data = qemuArgsTemplateData{
httpIp,
httpPort,
config.HTTPDir,
config.OutputDir,
config.VMName,
- sshHostPort,
+ commHostPort,
}
} else {
ictx.Data = qemuArgsTemplateData{
diff --git a/fix/fixer.go b/fix/fixer.go
index 8e3ef76e0..d77c23152 100644
--- a/fix/fixer.go
+++ b/fix/fixer.go
@@ -57,6 +57,7 @@ func init() {
"docker-tag-tags": new(FixerDockerTagtoTags),
"vsphere-iso-net-disk": new(FixerVSphereNetworkDisk),
"iso-checksum-type-and-url": new(FixerISOChecksumTypeAndURL),
+ "qemu-host-port": new(FixerQEMUHostPort),
}
FixerOrder = []string{
@@ -91,5 +92,6 @@ func init() {
"ssh-wait-timeout",
"vsphere-iso-net-disk",
"iso-checksum-type-and-url",
+ "qemu-host-port",
}
}
diff --git a/fix/fixer_qemu_host_port.go b/fix/fixer_qemu_host_port.go
new file mode 100644
index 000000000..c1f6a3e3a
--- /dev/null
+++ b/fix/fixer_qemu_host_port.go
@@ -0,0 +1,61 @@
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerQEMUHostPort updates ssh_host_port_min and ssh_host_port_max to host_port_min and host_port_max for QEMU builders
+type FixerQEMUHostPort struct{}
+
+func (FixerQEMUHostPort) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "qemu" {
+ continue
+ }
+
+ // replace ssh_host_port_min with host_port_min if it exists
+ sshHostPortMin, ok := builder["ssh_host_port_min"]
+ if ok {
+ delete(builder, "ssh_host_port_min")
+ builder["host_port_min"] = sshHostPortMin
+ }
+
+ // replace ssh_host_port_min with host_port_min if it exists
+ sshHostPortMax, ok := builder["ssh_host_port_max"]
+ if ok {
+ delete(builder, "ssh_host_port_max")
+ builder["host_port_max"] = sshHostPortMax
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerQEMUHostPort) Synopsis() string {
+ return `Updates ssh_host_port_min and ssh_host_port_max to host_port_min and host_port_max`
+}
+
+func (FixerQEMUHostPort) DeprecatedOptions() []string {
+ return []string{"ssh_host_port_max", "ssh_host_port_min"}
+}
diff --git a/fix/fixer_qemu_host_port_test.go b/fix/fixer_qemu_host_port_test.go
new file mode 100644
index 000000000..e2ec753c5
--- /dev/null
+++ b/fix/fixer_qemu_host_port_test.go
@@ -0,0 +1,61 @@
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerQEMUHostPort_impl(t *testing.T) {
+ var _ Fixer = new(FixerQEMUHostPort)
+}
+
+func TestFixerQEMUHostPort(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "type": "qemu",
+ "ssh_host_port_min": 2222,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "qemu",
+ "host_port_min": 2222,
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "qemu",
+ "ssh_host_port_max": 4444,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "qemu",
+ "host_port_max": 4444,
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerQEMUHostPort
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/hcl2template/parser.go b/hcl2template/parser.go
index 59efd69c0..5aab7d5d8 100644
--- a/hcl2template/parser.go
+++ b/hcl2template/parser.go
@@ -191,7 +191,7 @@ func (p *Parser) decodeConfig(f *hcl.File, cfg *PackerConfig) hcl.Diagnostics {
}
ref := source.Ref()
- if existing := cfg.Sources[ref]; existing != nil {
+ if existing, found := cfg.Sources[ref]; found {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Duplicate " + sourceLabel + " block",
@@ -205,7 +205,7 @@ func (p *Parser) decodeConfig(f *hcl.File, cfg *PackerConfig) hcl.Diagnostics {
}
if cfg.Sources == nil {
- cfg.Sources = map[SourceRef]*SourceBlock{}
+ cfg.Sources = map[SourceRef]SourceBlock{}
}
cfg.Sources[ref] = source
diff --git a/hcl2template/testdata/complete/build.pkr.hcl b/hcl2template/testdata/complete/build.pkr.hcl
index 5641e540b..327d2399f 100644
--- a/hcl2template/testdata/complete/build.pkr.hcl
+++ b/hcl2template/testdata/complete/build.pkr.hcl
@@ -5,6 +5,10 @@ build {
"source.virtualbox-iso.ubuntu-1204",
]
+ source "source.amazon-ebs.ubuntu-1604" {
+ string = "setting from build section"
+ }
+
provisioner "shell" {
name = "provisioner that does something"
not_squashed = var.foo
diff --git a/hcl2template/testdata/complete/sources.pkr.hcl b/hcl2template/testdata/complete/sources.pkr.hcl
index 2575929c7..8b05624d5 100644
--- a/hcl2template/testdata/complete/sources.pkr.hcl
+++ b/hcl2template/testdata/complete/sources.pkr.hcl
@@ -1,3 +1,9 @@
+
+source "amazon-ebs" "ubuntu-1604" {
+ int = 42
+}
+
+
source "virtualbox-iso" "ubuntu-1204" {
string = "string"
int = 42
@@ -85,4 +91,4 @@ source "virtualbox-iso" "ubuntu-1204" {
["c","d"]
]
}
-}
\ No newline at end of file
+}
diff --git a/hcl2template/types.build.go b/hcl2template/types.build.go
index bf5802771..829038c85 100644
--- a/hcl2template/types.build.go
+++ b/hcl2template/types.build.go
@@ -19,6 +19,7 @@ const (
var buildSchema = &hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{Type: buildFromLabel, LabelNames: []string{"type"}},
+ {Type: sourceLabel, LabelNames: []string{"reference"}},
{Type: buildProvisionerLabel, LabelNames: []string{"type"}},
{Type: buildPostProcessorLabel, LabelNames: []string{"type"}},
},
@@ -60,7 +61,7 @@ func (p *Parser) decodeBuildConfig(block *hcl.Block) (*BuildBlock, hcl.Diagnosti
var b struct {
Name string `hcl:"name,optional"`
- FromSources []string `hcl:"sources"`
+ FromSources []string `hcl:"sources,optional"`
Config hcl.Body `hcl:",remain"`
}
diags := gohcl.DecodeBody(block.Body, nil, &b)
@@ -98,6 +99,13 @@ func (p *Parser) decodeBuildConfig(block *hcl.Block) (*BuildBlock, hcl.Diagnosti
}
for _, block := range content.Blocks {
switch block.Type {
+ case sourceLabel:
+ ref, moreDiags := p.decodeBuildSource(block)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ build.Sources = append(build.Sources, ref)
case buildProvisionerLabel:
p, moreDiags := p.decodeProvisioner(block)
diags = append(diags, moreDiags...)
diff --git a/hcl2template/types.build.post-processor.go b/hcl2template/types.build.post-processor.go
index 8add11514..bedbb1ad0 100644
--- a/hcl2template/types.build.post-processor.go
+++ b/hcl2template/types.build.post-processor.go
@@ -49,7 +49,7 @@ func (p *Parser) decodePostProcessor(block *hcl.Block) (*PostProcessorBlock, hcl
return postProcessor, diags
}
-func (cfg *PackerConfig) startPostProcessor(source *SourceBlock, pp *PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.PostProcessor, hcl.Diagnostics) {
+func (cfg *PackerConfig) startPostProcessor(source SourceBlock, pp *PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.PostProcessor, hcl.Diagnostics) {
// ProvisionerBlock represents a detected but unparsed provisioner
var diags hcl.Diagnostics
diff --git a/hcl2template/types.build.provisioners.go b/hcl2template/types.build.provisioners.go
index df10d77dc..c41ba2eb4 100644
--- a/hcl2template/types.build.provisioners.go
+++ b/hcl2template/types.build.provisioners.go
@@ -77,7 +77,7 @@ func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Dia
return provisioner, diags
}
-func (cfg *PackerConfig) startProvisioner(source *SourceBlock, pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.Provisioner, hcl.Diagnostics) {
+func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.Provisioner, hcl.Diagnostics) {
var diags hcl.Diagnostics
provisioner, err := cfg.provisionersSchemas.Start(pb.PType)
diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go
index 7306f8763..81eb4bad8 100644
--- a/hcl2template/types.packer_config.go
+++ b/hcl2template/types.packer_config.go
@@ -18,7 +18,7 @@ type PackerConfig struct {
Basedir string
// Available Source blocks
- Sources map[SourceRef]*SourceBlock
+ Sources map[SourceRef]SourceBlock
// InputVariables and LocalVariables are the list of defined input and
// local variables. They are of the same type but are not used in the same
@@ -194,7 +194,7 @@ func (c *PackerConfig) evaluateLocalVariable(local *Local) hcl.Diagnostics {
// getCoreBuildProvisioners takes a list of provisioner block, starts according
// provisioners and sends parsed HCL2 over to it.
-func (cfg *PackerConfig) getCoreBuildProvisioners(source *SourceBlock, blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
+func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceBlock, blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := []packer.CoreBuildProvisioner{}
for _, pb := range blocks {
@@ -234,7 +234,7 @@ func (cfg *PackerConfig) getCoreBuildProvisioners(source *SourceBlock, blocks []
// getCoreBuildProvisioners takes a list of post processor block, starts
// according provisioners and sends parsed HCL2 over to it.
-func (cfg *PackerConfig) getCoreBuildPostProcessors(source *SourceBlock, blocks []*PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
+func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceBlock, blocks []*PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := []packer.CoreBuildPostProcessor{}
for _, ppb := range blocks {
@@ -262,15 +262,17 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build
for _, build := range cfg.Builds {
for _, from := range build.Sources {
- src, found := cfg.Sources[from]
+ src, found := cfg.Sources[from.Ref()]
if !found {
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + sourceLabel + " " + from.String(),
Subject: build.HCL2Ref.DefRange.Ptr(),
Severity: hcl.DiagError,
+ Detail: fmt.Sprintf("Known: %v", cfg.Sources),
})
continue
}
+ src.addition = from.addition
// Apply the -only and -except command-line options to exclude matching builds.
buildName := fmt.Sprintf("%s.%s", src.Type, src.Name)
diff --git a/hcl2template/types.packer_config_test.go b/hcl2template/types.packer_config_test.go
index 844038f19..e3675d478 100644
--- a/hcl2template/types.packer_config_test.go
+++ b/hcl2template/types.packer_config_test.go
@@ -1,10 +1,9 @@
package hcl2template
import (
- "path/filepath"
"testing"
- "time"
+ . "github.com/hashicorp/packer/hcl2template/internal"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
)
@@ -72,12 +71,16 @@ func TestParser_complete(t *testing.T) {
}),
},
},
- Sources: map[SourceRef]*SourceBlock{
- refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ refAWSEBSUbuntu1204: {Type: "amazon-ebs", Name: "ubuntu-1604"},
},
Builds: Builds{
&BuildBlock{
- Sources: []SourceRef{refVBIsoUbuntu1204},
+ Sources: []SourceRef{
+ refVBIsoUbuntu1204,
+ refAWSEBSUbuntu1204,
+ },
ProvisionerBlocks: []*ProvisionerBlock{
{
PType: "shell",
@@ -125,136 +128,40 @@ func TestParser_complete(t *testing.T) {
},
},
},
- },
- false,
- },
- {"dir with no config files",
- defaultParser,
- parseTestArgs{"testdata/empty", nil, nil},
- nil,
- true, true,
- nil,
- false,
- },
- {name: "inexistent dir",
- parser: defaultParser,
- args: parseTestArgs{"testdata/inexistent", nil, nil},
- parseWantCfg: nil,
- parseWantDiags: true,
- parseWantDiagHasErrors: true,
- },
- {name: "folder named build.pkr.hcl with an unknown src",
- parser: defaultParser,
- args: parseTestArgs{"testdata/build.pkr.hcl", nil, nil},
- parseWantCfg: &PackerConfig{
- Basedir: "testdata/build.pkr.hcl",
- Builds: Builds{
- &BuildBlock{
- Sources: []SourceRef{refAWSEBSUbuntu1204, refVBIsoUbuntu1204},
- ProvisionerBlocks: []*ProvisionerBlock{
- {PType: "shell"},
- {PType: "file"},
- },
- PostProcessors: []*PostProcessorBlock{
- {PType: "amazon-import"},
- },
- },
- },
- },
- parseWantDiags: false,
- parseWantDiagHasErrors: false,
- getBuildsWantBuilds: []packer.Build{},
- getBuildsWantDiags: true,
- },
- {name: "unknown block type",
- parser: defaultParser,
- args: parseTestArgs{"testdata/unknown", nil, nil},
- parseWantCfg: &PackerConfig{
- Basedir: "testdata/unknown",
- },
- parseWantDiags: true,
- parseWantDiagHasErrors: true,
- },
- {"provisioner with wrappers pause_before and max_retriers",
- defaultParser,
- parseTestArgs{"testdata/build/provisioner_paused_before_retry.pkr.hcl", nil, nil},
- &PackerConfig{
- Basedir: filepath.Join("testdata", "build"),
- Sources: map[SourceRef]*SourceBlock{
- refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
- },
- Builds: Builds{
- &BuildBlock{
- Sources: []SourceRef{refVBIsoUbuntu1204},
- ProvisionerBlocks: []*ProvisionerBlock{
- {
- PType: "shell",
- PauseBefore: time.Second * 10,
- MaxRetries: 5,
- },
- },
- },
- },
- },
- false, false,
- []packer.Build{
&packer.CoreBuild{
- Type: "virtualbox-iso.ubuntu-1204",
+ Type: "amazon-ebs.ubuntu-1604",
Prepared: true,
- Builder: emptyMockBuilder,
+ Builder: &MockBuilder{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ String: "setting from build section",
+ Int: 42,
+ Tags: []MockTag{},
+ },
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
Provisioners: []packer.CoreBuildProvisioner{
{
- PType: "shell",
- Provisioner: &packer.RetriedProvisioner{
- MaxRetries: 5,
- Provisioner: &packer.PausedProvisioner{
- PauseBefore: time.Second * 10,
- Provisioner: emptyMockProvisioner,
- },
- },
+ PType: "shell",
+ PName: "provisioner that does something",
+ Provisioner: basicMockProvisioner,
},
+ {PType: "file", Provisioner: basicMockProvisioner},
},
- PostProcessors: [][]packer.CoreBuildPostProcessor{},
- },
- },
- false,
- },
- {"provisioner with wrappers timeout",
- defaultParser,
- parseTestArgs{"testdata/build/provisioner_timeout.pkr.hcl", nil, nil},
- &PackerConfig{
- Basedir: filepath.Join("testdata", "build"),
- Sources: map[SourceRef]*SourceBlock{
- refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
- },
- Builds: Builds{
- &BuildBlock{
- Sources: []SourceRef{refVBIsoUbuntu1204},
- ProvisionerBlocks: []*ProvisionerBlock{
- {
- PType: "shell",
- Timeout: time.Second * 10,
- },
- },
- },
- },
- },
- false, false,
- []packer.Build{
- &packer.CoreBuild{
- Type: "virtualbox-iso.ubuntu-1204",
- Prepared: true,
- Builder: emptyMockBuilder,
- Provisioners: []packer.CoreBuildProvisioner{
+ PostProcessors: [][]packer.CoreBuildPostProcessor{
{
- PType: "shell",
- Provisioner: &packer.TimeoutProvisioner{
- Timeout: time.Second * 10,
- Provisioner: emptyMockProvisioner,
+ {
+ PType: "amazon-import",
+ PName: "something",
+ PostProcessor: basicMockPostProcessor,
+ },
+ {
+ PType: "amazon-import",
+ PostProcessor: basicMockPostProcessor,
},
},
},
- PostProcessors: [][]packer.CoreBuildPostProcessor{},
},
},
false,
diff --git a/hcl2template/types.source.go b/hcl2template/types.source.go
index dbc5a9724..94c7aa538 100644
--- a/hcl2template/types.source.go
+++ b/hcl2template/types.source.go
@@ -16,10 +16,24 @@ type SourceBlock struct {
Name string
block *hcl.Block
+
+ // addition will be merged into block to allow user to override builder settings
+ // per build.source block.
+ addition hcl.Body
}
-func (p *Parser) decodeSource(block *hcl.Block) (*SourceBlock, hcl.Diagnostics) {
- source := &SourceBlock{
+// decodeBuildSource reads a used source block from a build:
+// build {
+// source "type.example" {}
+// }
+func (p *Parser) decodeBuildSource(block *hcl.Block) (SourceRef, hcl.Diagnostics) {
+ ref := sourceRefFromString(block.Labels[0])
+ ref.addition = block.Body
+ return ref, nil
+}
+
+func (p *Parser) decodeSource(block *hcl.Block) (SourceBlock, hcl.Diagnostics) {
+ source := SourceBlock{
Type: block.Labels[0],
Name: block.Labels[1],
block: block,
@@ -33,13 +47,13 @@ func (p *Parser) decodeSource(block *hcl.Block) (*SourceBlock, hcl.Diagnostics)
Detail: fmt.Sprintf("known builders: %v", p.BuilderSchemas.List()),
Severity: hcl.DiagError,
})
- return nil, diags
+ return source, diags
}
return source, diags
}
-func (cfg *PackerConfig) startBuilder(source *SourceBlock, ectx *hcl.EvalContext, opts packer.GetBuildsOptions) (packer.Builder, hcl.Diagnostics, []string) {
+func (cfg *PackerConfig) startBuilder(source SourceBlock, ectx *hcl.EvalContext, opts packer.GetBuildsOptions) (packer.Builder, hcl.Diagnostics, []string) {
var diags hcl.Diagnostics
builder, err := cfg.builderSchemas.Start(source.Type)
@@ -52,7 +66,12 @@ func (cfg *PackerConfig) startBuilder(source *SourceBlock, ectx *hcl.EvalContext
return builder, diags, nil
}
- decoded, moreDiags := decodeHCL2Spec(source.block.Body, ectx, builder)
+ body := source.block.Body
+ if source.addition != nil {
+ body = hcl.MergeBodies([]hcl.Body{source.block.Body, source.addition})
+ }
+
+ decoded, moreDiags := decodeHCL2Spec(body, ectx, builder)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
return nil, diags, nil
@@ -92,6 +111,19 @@ func (source *SourceBlock) Ref() SourceRef {
type SourceRef struct {
Type string
Name string
+
+ // The content of this body will be merged into a new block to allow to
+ // override builder settings per build section.
+ addition hcl.Body
+}
+
+// the 'addition' field makes of ref a different entry in the sources map, so
+// Ref is here to make sure only one is returned.
+func (r *SourceRef) Ref() SourceRef {
+ return SourceRef{
+ Type: r.Type,
+ Name: r.Name,
+ }
}
// NoSource is the zero value of sourceRef, representing the absense of an
diff --git a/hcl2template/types.source_test.go b/hcl2template/types.source_test.go
index 423d20422..9a344765c 100644
--- a/hcl2template/types.source_test.go
+++ b/hcl2template/types.source_test.go
@@ -16,7 +16,7 @@ func TestParse_source(t *testing.T) {
parseTestArgs{"testdata/sources/basic.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "sources"),
- Sources: map[SourceRef]*SourceBlock{
+ Sources: map[SourceRef]SourceBlock{
{
Type: "virtualbox-iso",
Name: "ubuntu-1204",
@@ -65,7 +65,7 @@ func TestParse_source(t *testing.T) {
parseTestArgs{"testdata/sources/duplicate.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "sources"),
- Sources: map[SourceRef]*SourceBlock{
+ Sources: map[SourceRef]SourceBlock{
{
Type: "virtualbox-iso",
Name: "ubuntu-1204",
diff --git a/hcl2template/types.variables_test.go b/hcl2template/types.variables_test.go
index 15f5fc9f6..df87594eb 100644
--- a/hcl2template/types.variables_test.go
+++ b/hcl2template/types.variables_test.go
@@ -162,15 +162,17 @@ func TestParse_variables(t *testing.T) {
Name: "foo",
},
},
- Sources: map[SourceRef]*SourceBlock{
- SourceRef{"null", "null-builder"}: &SourceBlock{
+ Sources: map[SourceRef]SourceBlock{
+ SourceRef{"null", "null-builder", nil}: SourceBlock{
Name: "null-builder",
Type: "null",
},
},
Builds: Builds{
&BuildBlock{
- Sources: []SourceRef{SourceRef{"null", "null-builder"}},
+ Sources: []SourceRef{
+ {"null", "null-builder", nil},
+ },
},
},
},
diff --git a/helper/config/deprecated_options.go b/helper/config/deprecated_options.go
index 9875b3750..538d50fe5 100644
--- a/helper/config/deprecated_options.go
+++ b/helper/config/deprecated_options.go
@@ -38,4 +38,6 @@ var DeprecatedOptions = []string{
"disk_eagerly_scrub",
"iso_checksum_url",
"iso_checksum_type",
+ "ssh_host_port_max",
+ "ssh_host_port_min",
}
diff --git a/website/data/docs-navigation.js b/website/data/docs-navigation.js
index 9afe6a4aa..3b29ceaa9 100644
--- a/website/data/docs-navigation.js
+++ b/website/data/docs-navigation.js
@@ -14,6 +14,15 @@ export default [
'syntax',
'expressions',
'syntax-json',
+ {
+ category: 'blocks',
+ content: [
+ {
+ category: 'build',
+ content: [ 'source', 'provisioner', 'post-processor' ],
+ },
+ 'locals', 'source', 'variable' ],
+ },
{
category: 'functions',
content: [
diff --git a/website/pages/docs/builders/qemu.mdx b/website/pages/docs/builders/qemu.mdx
index 6cc0c02e3..a25907988 100644
--- a/website/pages/docs/builders/qemu.mdx
+++ b/website/pages/docs/builders/qemu.mdx
@@ -117,6 +117,22 @@ necessary for this build to succeed and can be found further down the page.
@include 'common/shutdowncommand/ShutdownConfig-not-required.mdx'
+## Communicator configuration
+
+### Optional common fields:
+
+@include 'helper/communicator/Config-not-required.mdx'
+
+@include 'builder/qemu/CommConfig-not-required.mdx'
+
+### Optional SSH fields:
+
+@include 'helper/communicator/SSH-not-required.mdx'
+
+### Optional WinRM fields:
+
+@include 'helper/communicator/WinRM-not-required.mdx'
+
## Boot Configuration
@include 'common/bootcommand/VNCConfig.mdx'
diff --git a/website/pages/docs/from-1.5/blocks/build/index.mdx b/website/pages/docs/from-1.5/blocks/build/index.mdx
new file mode 100644
index 000000000..10e6b53ec
--- /dev/null
+++ b/website/pages/docs/from-1.5/blocks/build/index.mdx
@@ -0,0 +1,35 @@
+---
+description: >
+ The source block defines what builders are started.
+layout: docs
+page_title: build - Blocks
+sidebar_title: build
+---
+
+# The `build` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `build` block defines what builders are started, how to `provision` them
+and if necessary what to do with their artifacts using `post-process`.
+
+`@include 'from-1.5/builds/example-block.mdx'`
+
+
+Define [top-level `source` blocks](/docs/from-1.5/blocks/source) to configure
+your builders. The list of available builders can be found in the
+[builders](/docs/builders) section.
+
+To use builders in a `build` block you can either:
+
+* Set the `sources` array of string with references to defined sources.
+
+* Define [build-level `source` blocks](/docs/from-1.5/blocks/build/source) or
+`sources` to use builders. This also allows you to set specific fields.
+
+## Related
+
+* A list of [community
+builders](/community-tools#community-builders) is available.
+
+* Create your own [custom builder](/docs/extending/custom-builders) !
diff --git a/website/pages/docs/from-1.5/blocks/build/post-processor.mdx b/website/pages/docs/from-1.5/blocks/build/post-processor.mdx
new file mode 100644
index 000000000..dd8c16afd
--- /dev/null
+++ b/website/pages/docs/from-1.5/blocks/build/post-processor.mdx
@@ -0,0 +1,29 @@
+---
+description: >
+ The post-processor block defines how a post-processor is configured.
+layout: docs
+page_title: post-processor - build - Blocks
+sidebar_title: post-processor
+---
+
+# The `post-processor` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `post-processor` block defines how a post-processor is configured.
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ post-processor "checksum" {
+ checksum_types = [ "md5", "sha512" ]
+ keep_input_artifact = true
+ }
+}
+```
+
+Post-processors run after the image is built by the builder and provisioned by
+the provisioner(s). Post-processors are optional, and they can be used to
+upload artifacts, re-package, or more. The list of available post-processors
+can be found in the [post-processors](/docs/post-processors) section.
\ No newline at end of file
diff --git a/website/pages/docs/from-1.5/blocks/build/provisioner.mdx b/website/pages/docs/from-1.5/blocks/build/provisioner.mdx
new file mode 100644
index 000000000..900fdacd9
--- /dev/null
+++ b/website/pages/docs/from-1.5/blocks/build/provisioner.mdx
@@ -0,0 +1,32 @@
+---
+description: >
+ The provisioner block defines how a provisioner is configured.
+layout: docs
+page_title: provisioner - build - Blocks
+sidebar_title: provisioner
+---
+
+# The `provisioner` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `provisioner` block defines how a provisioner is configured.
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ provisioner "shell" {
+ inline = [
+ "echo provisioning all the things",
+ "echo the value of 'foo' is '${var.foo}'",
+ ]
+ }
+}
+```
+
+Provisioners use builtin and third-party software to install and configure the
+machine image after booting. Provisioners prepare the system for use.
+
+The list of available provisioners can be found in the
+[provisioners](/docs/provisioners) section.
diff --git a/website/pages/docs/from-1.5/blocks/build/source.mdx b/website/pages/docs/from-1.5/blocks/build/source.mdx
new file mode 100644
index 000000000..73b8747a2
--- /dev/null
+++ b/website/pages/docs/from-1.5/blocks/build/source.mdx
@@ -0,0 +1,30 @@
+---
+description: >
+ A source block nested in a build block allows you to use an already defined
+ source and to set specific fields.
+layout: docs
+page_title: source - build - Blocks
+sidebar_title: source
+---
+
+# The `source` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+A `source` block nested in a `build` block allows to use an already defined
+source and to set specific fields.
+
+```hcl
+# builds.pkr.hcl
+build {
+ source "amazon-ebs.example" {
+ output = "specific-value"
+ }
+ # ...
+}
+```
+
+-> **Note:** It is **not allowed** to set the same field in a top-level source
+ block and in a used source block. For example, if in the above example, the
+ top-level "amazon-ebs.example" source block also had an `output` field;
+ Packer would error.
diff --git a/website/pages/docs/from-1.5/blocks/index.mdx b/website/pages/docs/from-1.5/blocks/index.mdx
new file mode 100644
index 000000000..ea4fc2ed8
--- /dev/null
+++ b/website/pages/docs/from-1.5/blocks/index.mdx
@@ -0,0 +1,31 @@
+---
+layout: docs
+page_title: Blocks - Configuration Language
+sidebar_title: Blocks
+description: |-
+ The HCL language has a number of blocks that can be used to configure builds.
+---
+
+# Built-in Blocks
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The Packer - HCL2 language includes a number of built-in blocks that you can
+use. A block is a container for configuration.
+
+Blocks can be defined in multiple files and `packer build folder` will build
+using solely the files from a directory named `folder`.
+
+Packer does not support user-defined blocks and so only the blocks built in to
+the language are available for use. The navigation for this section includes a
+list of all of the available built-in HCL2 blocks.
+
+## Config example:
+
+`@include 'from-1.5/variables/foo-block.mdx'`
+
+`@include 'from-1.5/locals/example-block.mdx'`
+
+`@include 'from-1.5/sources/example-block.mdx'`
+
+`@include 'from-1.5/builds/example-block.mdx'`
diff --git a/website/pages/docs/from-1.5/blocks/locals.mdx b/website/pages/docs/from-1.5/blocks/locals.mdx
new file mode 100644
index 000000000..0a3c767c3
--- /dev/null
+++ b/website/pages/docs/from-1.5/blocks/locals.mdx
@@ -0,0 +1,23 @@
+---
+description: >
+ The locals block also called the local-variable block defines locals within
+ your Packer configuration.
+layout: docs
+page_title: locals - Blocks
+sidebar_title: locals
+---
+
+# The `locals` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `locals` block, also called the `local-variable` block, defines locals within
+your Packer configuration.
+
+`@include 'from-1.5/locals/example-block.mdx'`
+
+# More on variables
+
+- Read the [full locals](/docs/from-1.5/locals) description for a more
+ thorough read.
+- Read the [variables guide](/guides/hcl/variables) for more examples.
diff --git a/website/pages/docs/from-1.5/blocks/source.mdx b/website/pages/docs/from-1.5/blocks/source.mdx
new file mode 100644
index 000000000..f129718ef
--- /dev/null
+++ b/website/pages/docs/from-1.5/blocks/source.mdx
@@ -0,0 +1,50 @@
+---
+description: >
+ The top-level source block defines reusable builder configuration blocks
+layout: docs
+page_title: source - Blocks
+sidebar_title: source
+---
+
+# The `source` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The top-level `source` block defines reusable builder configuration blocks:
+
+`@include 'from-1.5/sources/example-block.mdx'`
+
+You can start builders by refering to those source blocks form a [`build`
+block](/docs/from-1.5/blocks/build), for example :
+
+```hcl
+build {
+ source = [
+ # Here Packer will use a default ami_name when saving the image.
+ "sources.amazon-ebs.example",
+ "sources.amazon-ebs.foo",
+ ]
+}
+```
+
+The build-level [`source` block](/docs/from-1.5/blocks/build/source) allows to
+set specific source fields.
+
+```hcl
+build {
+ source "sources.amazon-ebs.example" {
+ # Here Packer will use the provided ami_name instead of defaulting it.
+ ami_name = "specific"
+ }
+}
+```
+
+## Related
+
+* The list of available builders can be found in the [builders](/docs/builders)
+ section.
+
+* A list of [community
+ builders](/community-tools#community-builders) is available.
+
+* Create your own [custom builder](/docs/extending/custom-builders) !
diff --git a/website/pages/docs/from-1.5/blocks/variable.mdx b/website/pages/docs/from-1.5/blocks/variable.mdx
new file mode 100644
index 000000000..16bf86f0f
--- /dev/null
+++ b/website/pages/docs/from-1.5/blocks/variable.mdx
@@ -0,0 +1,37 @@
+---
+description: >
+ The variable block, also called the input-variable block, defines variables
+ within your Packer configuration.
+layout: docs
+page_title: variable - Blocks
+sidebar_title: variable
+---
+
+# The `variable` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `variable` block, also called the `input-variable` block, defines variables
+within your Packer configuration. An input-variable cannot be used in another
+input variable: we recommend using [locals](/docs/from-1.5/blocks/locals) for that instead.
+
+`@include 'from-1.5/variables/foo-block.mdx'`
+
+## Default value
+
+If a default value is set, the variable is optional. Otherwise, the variable
+**must** be set.
+
+`@include 'from-1.5/variables/assignment.mdx'`
+
+Example of a variable assignment from a file:
+
+`@include 'from-1.5/variables/foo-pkrvar.mdx'`
+
+`@include 'from-1.5/variables/must-be-set.mdx'`
+
+# More on variables
+
+- Read the [full variables](/docs/from-1.5/variables) description for a more
+ thorough read.
+- Read the [variables guide](/guides/hcl/variables) for more examples.
diff --git a/website/pages/docs/from-1.5/expressions.mdx b/website/pages/docs/from-1.5/expressions.mdx
index b7ecdf8d4..cd3ef307d 100644
--- a/website/pages/docs/from-1.5/expressions.mdx
+++ b/website/pages/docs/from-1.5/expressions.mdx
@@ -9,11 +9,7 @@ description: |-
# Expressions
--> **Note:** This page is about HCL2 in Packer 1.5 and later. HCL2 support for
-Packer is still in Beta. Please see the [Packer Issue
-Tracker](https://github.com/hashicorp/packer/issues/9176) for a list of
-supported features. For the old-style stable configuration language see
-[template docs](/docs/templates).
+`@include 'from-1.5/beta-hcl2-note.mdx'`
_Expressions_ are used to refer to or compute values within a configuration.
The simplest expressions are just literal values, like `"hello"` or `5`, but
diff --git a/website/pages/docs/from-1.5/functions/index.mdx b/website/pages/docs/from-1.5/functions/index.mdx
index 525f15fd2..acfa04087 100644
--- a/website/pages/docs/from-1.5/functions/index.mdx
+++ b/website/pages/docs/from-1.5/functions/index.mdx
@@ -9,9 +9,7 @@ description: |-
# Built-in Functions
--> **Note:** This page is about HCL2 in Packer 1.5 and later. HCL2 support for
-Packer is still in Beta. For the old-style stable configuration language see
-[template docs](/docs/templates).
+`@include 'from-1.5/beta-hcl2-note.mdx'`
The HCL language includes a number of built-in functions that you can
call from within expressions to transform and combine values. The general
diff --git a/website/pages/docs/from-1.5/index.mdx b/website/pages/docs/from-1.5/index.mdx
index d2d218d37..e5fb91b29 100644
--- a/website/pages/docs/from-1.5/index.mdx
+++ b/website/pages/docs/from-1.5/index.mdx
@@ -10,11 +10,7 @@ description: |-
# HCL Configuration Language
--> **Note:** This page is about HCL2 in Packer 1.5 and later. HCL2 support for
-Packer is still in Beta. Please see the [Packer Issue
-Tracker](https://github.com/hashicorp/packer/issues/9176) for a list of
-supported features. For the old-style stable configuration language see
-[template docs](/docs/templates).
+`@include 'from-1.5/beta-hcl2-note.mdx'`
Packer uses the Hashicorp Configuration Language - HCL - designed to allow
concise descriptions of the required steps to get to a build file. This page
diff --git a/website/pages/docs/from-1.5/locals.mdx b/website/pages/docs/from-1.5/locals.mdx
index 2d2f45a3d..f482be743 100644
--- a/website/pages/docs/from-1.5/locals.mdx
+++ b/website/pages/docs/from-1.5/locals.mdx
@@ -9,11 +9,7 @@ description: >-
# Local Values
--> **Note:** This page is about HCL2 in Packer 1.5 and later. HCL2 support for
-Packer is still in Beta. Please see the [Packer Issue
-Tracker](https://github.com/hashicorp/packer/issues/9176) for a list of
-supported features. For the old-style stable configuration language see
-[template docs](/docs/templates).
+`@include 'from-1.5/beta-hcl2-note.mdx'`
Local values assign a name to an expression, that can then be used multiple
times within a folder.
diff --git a/website/pages/docs/from-1.5/syntax-json.mdx b/website/pages/docs/from-1.5/syntax-json.mdx
index 2eb90708f..238b1f0ca 100644
--- a/website/pages/docs/from-1.5/syntax-json.mdx
+++ b/website/pages/docs/from-1.5/syntax-json.mdx
@@ -9,11 +9,7 @@ description: |-
# JSON Configuration Syntax
--> **Note:** This page is about HCL2 in Packer 1.5 and later. Whilst HCL2
-supports JSON the JSON - JSON and the HCL2 - JSON have differents formats for
-Packer. HCL2 support for Packer is still in Beta. For the old-style stable
-configuration language see [template
-docs](/docs/templates).
+`@include 'from-1.5/beta-hcl2-note.mdx'`
Most Packer configurations are written in [the native HCL
syntax](/docs/from-1.5/syntax), which is designed to be easy for humans to read and
diff --git a/website/pages/docs/from-1.5/syntax.mdx b/website/pages/docs/from-1.5/syntax.mdx
index 602d22512..ce6e8e5f7 100644
--- a/website/pages/docs/from-1.5/syntax.mdx
+++ b/website/pages/docs/from-1.5/syntax.mdx
@@ -10,11 +10,7 @@ description: |-
# HCL Configuration Syntax
--> **Note:** This page is about HCL2 in Packer 1.5 and later. HCL2 support for
-Packer is still in Beta. Please see the [Packer Issue
-Tracker](https://github.com/hashicorp/packer/issues/9176) for a list of
-supported features. For the old-style stable configuration language see
-[template docs](/docs/templates).
+`@include 'from-1.5/beta-hcl2-note.mdx'`
Other pages in this section have described various configuration constructs
that can appear in HCL. This page describes the lower-level syntax of the
diff --git a/website/pages/docs/from-1.5/variables.mdx b/website/pages/docs/from-1.5/variables.mdx
index 60f6214e8..f8ee0752f 100644
--- a/website/pages/docs/from-1.5/variables.mdx
+++ b/website/pages/docs/from-1.5/variables.mdx
@@ -9,11 +9,7 @@ description: |-
# Input Variables
--> **Note:** This page is about HCL2 in Packer 1.5 and later. HCL2 support for
-Packer is still in Beta. Please see the [Packer Issue
-Tracker](https://github.com/hashicorp/packer/issues/9176) for a list of
-supported features. For the old-style stable configuration language see
-[template docs](/docs/templates).
+`@include 'from-1.5/beta-hcl2-note.mdx'`
Input variables serve as parameters for a Packer build, allowing aspects of the
build to be customized without altering the build's own source code.
@@ -155,15 +151,7 @@ documentation about the build, and so it should be written from the perspective
of the user of the build rather than its maintainer. For commentary for build
maintainers, use comments.
-## Assigning Values to build Variables
-
-When variables are declared in the build of your configuration, they can be set
-in a number of ways:
-
-- Individually, with the `-var` command line option.
-- In variable definitions (`.pkrvars.hcl`) files, either specified on the
- command line or automatically loaded.
-- As environment variables.
+`@include 'from-1.5/variables/assignment.mdx'`
The following sections describe these options in more detail.
@@ -285,40 +273,7 @@ precedence over earlier ones:
~> **Important:** Variables with map and object values behave the same way as
other variables: the last value found overrides the previous values.
-### A variable value must be known:
-
-Take the following variable for example:
-
-```hcl
-variable "foo" {
- type = string
-```
-
-Here `foo` must have a known value but you can default it to `null` to make
-this behavior optional :
-
-| | no default | `default = null` | `default = "xy"` |
-| :---------------------------: | :--------------------------: | :--------------: | :--------------: |
-| foo unused | error, "foo needs to be set" | - | - |
-| var.foo | error, "foo needs to be set" | null¹ | xy |
-| `PKR_VAR_foo=yz`
var.foo | yz | yz | yz |
-| `-var foo=yz`
var.foo | yz | yz | yz |
-
-1: Null is a valid value. Packer will only error when the receiving field needs
-a value, example:
-
-```hcl
-variable "example" {
- type = string
- default = null
-}
-
-source "example" "foo" {
- arg = var.example
-}
-```
-
-In the above case, as long as "arg" is optional for an "example" source, there is no error and arg won’t be set.
+`@include 'from-1.5/variables/must-be-set.mdx'`
### Setting an unknown variable will not always fail:
diff --git a/website/pages/partials/builder/qemu/CommConfig-not-required.mdx b/website/pages/partials/builder/qemu/CommConfig-not-required.mdx
new file mode 100644
index 000000000..53f6138ba
--- /dev/null
+++ b/website/pages/partials/builder/qemu/CommConfig-not-required.mdx
@@ -0,0 +1,14 @@
+
+
+- `host_port_min` (int) - The minimum port to use for the Communicator port on the host machine which is forwarded
+ to the SSH or WinRM port on the guest machine. By default this is 2222.
+
+- `host_port_max` (int) - The maximum port to use for the Communicator port on the host machine which is forwarded
+ to the SSH or WinRM port on the guest machine. Because Packer often runs in parallel,
+ Packer will choose a randomly available port in this range to use as the
+ host port. By default this is 4444.
+
+- `skip_nat_mapping` (bool) - Defaults to false. When enabled, Packer
+ does not setup forwarded port mapping for communicator (SSH or WinRM) requests and uses ssh_port or winrm_port
+ on the host to communicate to the virtual machine.
+
\ No newline at end of file
diff --git a/website/pages/partials/builder/qemu/Config-not-required.mdx b/website/pages/partials/builder/qemu/Config-not-required.mdx
index edc950048..d6a40041e 100644
--- a/website/pages/partials/builder/qemu/Config-not-required.mdx
+++ b/website/pages/partials/builder/qemu/Config-not-required.mdx
@@ -211,12 +211,6 @@
- `qmp_socket_path` (string) - QMP Socket Path when `qmp_enable` is true. Defaults to
`output_directory`/`vm_name`.monitor.
-- `ssh_host_port_min` (int) - The minimum and maximum port to use for the SSH port on the host machine
- which is forwarded to the SSH port on the guest machine. Because Packer
- often runs in parallel, Packer will choose a randomly available port in
- this range to use as the host port. By default this is 2222 to 4444.
-
-- `ssh_host_port_max` (int) - SSH Host Port Max
- `use_default_display` (bool) - If true, do not pass a -display option
to qemu, allowing it to choose the default. This may be needed when running
under macOS, and getting errors about sdl not being available.
diff --git a/website/pages/partials/builders/community_builders.mdx b/website/pages/partials/builders/community_builders.mdx
index ffd7c068c..79598629b 100644
--- a/website/pages/partials/builders/community_builders.mdx
+++ b/website/pages/partials/builders/community_builders.mdx
@@ -5,10 +5,6 @@
- [packer-builder-arm-image](https://github.com/solo-io/packer-builder-arm-image) - simple builder lets you extend on existing system images.
- [packer-builder-arm](https://github.com/mkaczanowski/packer-builder-arm) - flexible builder lets you extend or build images from scratch with variety of options (ie. custom partition table).
-- [vSphere builder](https://github.com/jetbrains-infra/packer-builder-vsphere) -
- A builder for interacting directly with the vSphere API rather than the esx
- host directly.
-
- [Vultr builder](https://github.com/vultr/packer-builder-vultr) - A builder
for creating [Vultr](https://www.vultr.com/) snapshots.
diff --git a/website/pages/partials/from-1.5/beta-hcl2-note.mdx b/website/pages/partials/from-1.5/beta-hcl2-note.mdx
new file mode 100644
index 000000000..c9f996646
--- /dev/null
+++ b/website/pages/partials/from-1.5/beta-hcl2-note.mdx
@@ -0,0 +1,5 @@
+-> **Note:** This page is about HCL2 in Packer 1.5 and later. HCL2 support for
+Packer is still in Beta. Please see the [Packer Issue
+Tracker](https://github.com/hashicorp/packer/issues/9176) for a list of
+supported features. For the old-style stable configuration language see
+[template docs](/docs/templates).
\ No newline at end of file
diff --git a/website/pages/partials/from-1.5/builds/example-block.mdx b/website/pages/partials/from-1.5/builds/example-block.mdx
new file mode 100644
index 000000000..811ca559c
--- /dev/null
+++ b/website/pages/partials/from-1.5/builds/example-block.mdx
@@ -0,0 +1,28 @@
+```hcl
+# build.pkr.hcl
+build {
+
+ sources = [
+ # use the plural `sources` block to simply use sources
+ # without changing any field.
+ "source.amazon-ebs.example",
+ ]
+
+ source "source.amazon-ebs.example" {
+ # Use the singular `source` block set
+ # specific fields.
+ # Note that fields cannot be overwritten, in other words, you cannot
+ # set the 'output' field from the top-level source block and here.
+ output = "different value"
+ name = var.foo
+ }
+
+ provisioner "shell-local" {
+ inline = ["echo Hello World"]
+ }
+
+ post-processor "shell-local" {
+ inline = ["echo Hello World"]
+ }
+}
+```
\ No newline at end of file
diff --git a/website/pages/partials/from-1.5/locals/example-block.mdx b/website/pages/partials/from-1.5/locals/example-block.mdx
new file mode 100644
index 000000000..c0cb5e663
--- /dev/null
+++ b/website/pages/partials/from-1.5/locals/example-block.mdx
@@ -0,0 +1,9 @@
+```hcl
+# locals.pkr.hcl
+locals {
+ # locals can be bare values like:
+ wee = local.baz
+ # locals can also be set with input variables :
+ baz = "Foo is '${var.foo}'"
+}
+```
\ No newline at end of file
diff --git a/website/pages/partials/from-1.5/sources/example-block.mdx b/website/pages/partials/from-1.5/sources/example-block.mdx
new file mode 100644
index 000000000..05b2c5012
--- /dev/null
+++ b/website/pages/partials/from-1.5/sources/example-block.mdx
@@ -0,0 +1,6 @@
+```hcl
+# sources.pkr.hcl
+source "amazon-ebs" "example" {
+ // ...
+}
+```
\ No newline at end of file
diff --git a/website/pages/partials/from-1.5/variables/assignment.mdx b/website/pages/partials/from-1.5/variables/assignment.mdx
new file mode 100644
index 000000000..c4cc41297
--- /dev/null
+++ b/website/pages/partials/from-1.5/variables/assignment.mdx
@@ -0,0 +1,8 @@
+## Assigning Values to build Variables
+
+Once a variable is declared in your configuration, you can set it:
+
+- Individually, with the `-var foo=bar` command line option.
+- In variable definitions (`.pkrvars.hcl`) files, either specified on the
+ command line or automatically loaded.
+- As environment variables, for example: `PKR_VAR_foo=bar`
\ No newline at end of file
diff --git a/website/pages/partials/from-1.5/variables/foo-block.mdx b/website/pages/partials/from-1.5/variables/foo-block.mdx
new file mode 100644
index 000000000..ca6601526
--- /dev/null
+++ b/website/pages/partials/from-1.5/variables/foo-block.mdx
@@ -0,0 +1,8 @@
+```hcl
+# variables.pkr.hcl
+variable "foo" {
+ type = string
+ default = "the default value of the `foo` variable"
+ description = "description of the `foo` variable"
+}
+```
\ No newline at end of file
diff --git a/website/pages/partials/from-1.5/variables/foo-pkrvar.mdx b/website/pages/partials/from-1.5/variables/foo-pkrvar.mdx
new file mode 100644
index 000000000..04f44e1be
--- /dev/null
+++ b/website/pages/partials/from-1.5/variables/foo-pkrvar.mdx
@@ -0,0 +1,4 @@
+```hcl
+# foo.pkrvars.hcl
+foo = "value"
+```
diff --git a/website/pages/partials/from-1.5/variables/must-be-set.mdx b/website/pages/partials/from-1.5/variables/must-be-set.mdx
new file mode 100644
index 000000000..1413aeab2
--- /dev/null
+++ b/website/pages/partials/from-1.5/variables/must-be-set.mdx
@@ -0,0 +1,34 @@
+## A variable value must be known:
+
+Take the following variable for example:
+
+```hcl
+variable "foo" {
+ type = string
+```
+
+Here `foo` must have a known value but you can default it to `null` to make
+this behavior optional :
+
+| | no default | `default = null` | `default = "xy"` |
+| :---------------------------: | :--------------------------: | :--------------: | :--------------: |
+| foo unused | error, "foo needs to be set" | - | - |
+| var.foo | error, "foo needs to be set" | null¹ | xy |
+| `PKR_VAR_foo=yz`
var.foo | yz | yz | yz |
+| `-var foo=yz`
var.foo | yz | yz | yz |
+
+1: Null is a valid value. Packer will only error when the receiving field needs
+a value, example:
+
+```hcl
+variable "example" {
+ type = string
+ default = null
+}
+
+source "example" "foo" {
+ arg = var.example
+}
+```
+
+In the above case, as long as "arg" is optional for an "example" source, there is no error and arg won’t be set.
\ No newline at end of file