Merge branch 'master' into master
This commit is contained in:
commit
f09fd790b7
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
|
@ -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{
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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...)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -38,4 +38,6 @@ var DeprecatedOptions = []string{
|
|||
"disk_eagerly_scrub",
|
||||
"iso_checksum_url",
|
||||
"iso_checksum_type",
|
||||
"ssh_host_port_max",
|
||||
"ssh_host_port_min",
|
||||
}
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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) !
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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'`
|
|
@ -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.
|
|
@ -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) !
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 won’t be set.
|
||||
`@include 'from-1.5/variables/must-be-set.mdx'`
|
||||
|
||||
### Setting an unknown variable will not always fail:
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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).
|
|
@ -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"]
|
||||
}
|
||||
}
|
||||
```
|
|
@ -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}'"
|
||||
}
|
||||
```
|
|
@ -0,0 +1,6 @@
|
|||
```hcl
|
||||
# sources.pkr.hcl
|
||||
source "amazon-ebs" "example" {
|
||||
// ...
|
||||
}
|
||||
```
|
|
@ -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`
|
|
@ -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"
|
||||
}
|
||||
```
|
|
@ -0,0 +1,4 @@
|
|||
```hcl
|
||||
# foo.pkrvars.hcl
|
||||
foo = "value"
|
||||
```
|
|
@ -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 won’t be set.
|
Loading…
Reference in New Issue