Merge branch 'master' into master

This commit is contained in:
Adrien Delorme 2020-06-02 15:12:44 +02:00 committed by GitHub
commit f09fd790b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 949 additions and 308 deletions

View File

@ -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]

View File

@ -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,

View File

@ -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},

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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{

View File

@ -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",
}
}

View File

@ -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"}
}

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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"]
]
}
}
}

View File

@ -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...)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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",

View File

@ -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},
},
},
},
},

View File

@ -38,4 +38,6 @@ var DeprecatedOptions = []string{
"disk_eagerly_scrub",
"iso_checksum_url",
"iso_checksum_type",
"ssh_host_port_max",
"ssh_host_port_min",
}

View File

@ -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: [

View File

@ -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'

View File

@ -0,0 +1,35 @@
---
description: >
The source block defines what builders are started.
layout: docs
page_title: build - Blocks
sidebar_title: <tt>build</tt>
---
# 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) !

View File

@ -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: <tt>post-processor</tt>
---
# 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.

View File

@ -0,0 +1,32 @@
---
description: >
The provisioner block defines how a provisioner is configured.
layout: docs
page_title: provisioner - build - Blocks
sidebar_title: <tt>provisioner</tt>
---
# 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.

View File

@ -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: <tt>source</tt>
---
# 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.

View File

@ -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'`

View File

@ -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: <tt>locals</tt>
---
# 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.

View File

@ -0,0 +1,50 @@
---
description: >
The top-level source block defines reusable builder configuration blocks
layout: docs
page_title: source - Blocks
sidebar_title: <tt>source</tt>
---
# 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) !

View File

@ -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: <tt>variable</tt>
---
# 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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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`<br />var.foo | yz | yz | yz |
| `-var foo=yz`<br />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 wont be set.
`@include 'from-1.5/variables/must-be-set.mdx'`
### Setting an unknown variable will not always fail:

View File

@ -0,0 +1,14 @@
<!-- Code generated from the comments of the CommConfig struct in builder/qemu/comm_config.go; DO NOT EDIT MANUALLY -->
- `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.

View File

@ -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.

View File

@ -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.

View File

@ -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).

View File

@ -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"]
}
}
```

View File

@ -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}'"
}
```

View File

@ -0,0 +1,6 @@
```hcl
# sources.pkr.hcl
source "amazon-ebs" "example" {
// ...
}
```

View File

@ -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`

View File

@ -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"
}
```

View File

@ -0,0 +1,4 @@
```hcl
# foo.pkrvars.hcl
foo = "value"
```

View File

@ -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`<br />var.foo | yz | yz | yz |
| `-var foo=yz`<br />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 wont be set.