flatten boot command config and implement for vmware
This commit is contained in:
parent
84894ca459
commit
408eba88ad
|
@ -2,30 +2,20 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer/template/interpolate"
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RunConfig struct {
|
type RunConfig struct {
|
||||||
Headless bool `mapstructure:"headless"`
|
Headless bool `mapstructure:"headless"`
|
||||||
RawBootWait string `mapstructure:"boot_wait"`
|
|
||||||
DisableVNC bool `mapstructure:"disable_vnc"`
|
|
||||||
BootCommand []string `mapstructure:"boot_command"`
|
|
||||||
|
|
||||||
VNCBindAddress string `mapstructure:"vnc_bind_address"`
|
VNCBindAddress string `mapstructure:"vnc_bind_address"`
|
||||||
VNCPortMin uint `mapstructure:"vnc_port_min"`
|
VNCPortMin uint `mapstructure:"vnc_port_min"`
|
||||||
VNCPortMax uint `mapstructure:"vnc_port_max"`
|
VNCPortMax uint `mapstructure:"vnc_port_max"`
|
||||||
VNCDisablePassword bool `mapstructure:"vnc_disable_password"`
|
VNCDisablePassword bool `mapstructure:"vnc_disable_password"`
|
||||||
|
|
||||||
BootWait time.Duration ``
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
|
||||||
if c.RawBootWait == "" {
|
|
||||||
c.RawBootWait = "10s"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *RunConfig) Prepare(ctx *interpolate.Context) (errs []error) {
|
||||||
if c.VNCPortMin == 0 {
|
if c.VNCPortMin == 0 {
|
||||||
c.VNCPortMin = 5900
|
c.VNCPortMin = 5900
|
||||||
}
|
}
|
||||||
|
@ -38,25 +28,9 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
||||||
c.VNCBindAddress = "127.0.0.1"
|
c.VNCBindAddress = "127.0.0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
var errs []error
|
|
||||||
var err error
|
|
||||||
if len(c.BootCommand) > 0 && c.DisableVNC {
|
|
||||||
errs = append(errs,
|
|
||||||
fmt.Errorf("A boot command cannot be used when vnc is disabled."))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.RawBootWait != "" {
|
|
||||||
c.BootWait, err = time.ParseDuration(c.RawBootWait)
|
|
||||||
if err != nil {
|
|
||||||
errs = append(
|
|
||||||
errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.VNCPortMin > c.VNCPortMax {
|
if c.VNCPortMin > c.VNCPortMax {
|
||||||
errs = append(
|
errs = append(errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max"))
|
||||||
errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return errs
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRunConfigPrepare(t *testing.T) {
|
|
||||||
var c *RunConfig
|
|
||||||
|
|
||||||
// Test a default boot_wait
|
|
||||||
c = new(RunConfig)
|
|
||||||
c.RawBootWait = ""
|
|
||||||
errs := c.Prepare(testConfigTemplate(t))
|
|
||||||
if len(errs) > 0 {
|
|
||||||
t.Fatalf("bad: %#v", errs)
|
|
||||||
}
|
|
||||||
if c.RawBootWait != "10s" {
|
|
||||||
t.Fatalf("bad value: %s", c.RawBootWait)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with a bad boot_wait
|
|
||||||
c = new(RunConfig)
|
|
||||||
c.RawBootWait = "this is not good"
|
|
||||||
errs = c.Prepare(testConfigTemplate(t))
|
|
||||||
if len(errs) == 0 {
|
|
||||||
t.Fatal("should error")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with a good one
|
|
||||||
c = new(RunConfig)
|
|
||||||
c.RawBootWait = "5s"
|
|
||||||
errs = c.Prepare(testConfigTemplate(t))
|
|
||||||
if len(errs) > 0 {
|
|
||||||
t.Fatalf("bad: %#v", errs)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
// Produces:
|
// Produces:
|
||||||
// <nothing>
|
// <nothing>
|
||||||
type StepTypeBootCommand struct {
|
type StepTypeBootCommand struct {
|
||||||
BootCommand []string
|
BootCommand string
|
||||||
VNCEnabled bool
|
VNCEnabled bool
|
||||||
BootWait time.Duration
|
BootWait time.Duration
|
||||||
VMName string
|
VMName string
|
||||||
|
@ -118,8 +118,7 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag)
|
||||||
d := bootcommand.NewVNCDriver(c)
|
d := bootcommand.NewVNCDriver(c)
|
||||||
|
|
||||||
ui.Say("Typing the boot command over VNC...")
|
ui.Say("Typing the boot command over VNC...")
|
||||||
for i, command := range s.BootCommand {
|
command, err := interpolate.Render(s.BootCommand, &s.Ctx)
|
||||||
command, err := interpolate.Render(command, &s.Ctx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error preparing boot command: %s", err)
|
err := fmt.Errorf("Error preparing boot command: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -143,9 +142,8 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pauseFn != nil {
|
if pauseFn != nil {
|
||||||
pauseFn(multistep.DebugLocationAfterRun, fmt.Sprintf("boot_command[%d]: %s", i, command), state)
|
pauseFn(multistep.DebugLocationAfterRun,
|
||||||
}
|
fmt.Sprintf("boot_command: %s", command), state)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
||||||
"github.com/hashicorp/packer/common"
|
"github.com/hashicorp/packer/common"
|
||||||
|
"github.com/hashicorp/packer/common/boot_command"
|
||||||
"github.com/hashicorp/packer/helper/communicator"
|
"github.com/hashicorp/packer/helper/communicator"
|
||||||
"github.com/hashicorp/packer/helper/config"
|
"github.com/hashicorp/packer/helper/config"
|
||||||
"github.com/hashicorp/packer/helper/multistep"
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
|
@ -30,6 +31,7 @@ type Config struct {
|
||||||
common.HTTPConfig `mapstructure:",squash"`
|
common.HTTPConfig `mapstructure:",squash"`
|
||||||
common.ISOConfig `mapstructure:",squash"`
|
common.ISOConfig `mapstructure:",squash"`
|
||||||
common.FloppyConfig `mapstructure:",squash"`
|
common.FloppyConfig `mapstructure:",squash"`
|
||||||
|
bootcommand.VNCConfig `mapstructure:",squash"`
|
||||||
vmwcommon.DriverConfig `mapstructure:",squash"`
|
vmwcommon.DriverConfig `mapstructure:",squash"`
|
||||||
vmwcommon.OutputConfig `mapstructure:",squash"`
|
vmwcommon.OutputConfig `mapstructure:",squash"`
|
||||||
vmwcommon.RunConfig `mapstructure:",squash"`
|
vmwcommon.RunConfig `mapstructure:",squash"`
|
||||||
|
@ -122,6 +124,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(&b.config.ctx)...)
|
errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(&b.config.ctx)...)
|
||||||
errs = packer.MultiErrorAppend(errs, b.config.VMXConfig.Prepare(&b.config.ctx)...)
|
errs = packer.MultiErrorAppend(errs, b.config.VMXConfig.Prepare(&b.config.ctx)...)
|
||||||
errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(&b.config.ctx)...)
|
errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(&b.config.ctx)...)
|
||||||
|
errs = packer.MultiErrorAppend(errs, b.config.VNCConfig.Prepare(&b.config.ctx)...)
|
||||||
|
|
||||||
if b.config.DiskName == "" {
|
if b.config.DiskName == "" {
|
||||||
b.config.DiskName = "disk"
|
b.config.DiskName = "disk"
|
||||||
|
@ -325,7 +328,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
&vmwcommon.StepTypeBootCommand{
|
&vmwcommon.StepTypeBootCommand{
|
||||||
BootWait: b.config.BootWait,
|
BootWait: b.config.BootWait,
|
||||||
VNCEnabled: !b.config.DisableVNC,
|
VNCEnabled: !b.config.DisableVNC,
|
||||||
BootCommand: b.config.BootCommand,
|
BootCommand: b.config.FlatBootCommand(),
|
||||||
VMName: b.config.VMName,
|
VMName: b.config.VMName,
|
||||||
Ctx: b.config.ctx,
|
Ctx: b.config.ctx,
|
||||||
},
|
},
|
||||||
|
|
|
@ -93,7 +93,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
&vmwcommon.StepTypeBootCommand{
|
&vmwcommon.StepTypeBootCommand{
|
||||||
BootWait: b.config.BootWait,
|
BootWait: b.config.BootWait,
|
||||||
VNCEnabled: !b.config.DisableVNC,
|
VNCEnabled: !b.config.DisableVNC,
|
||||||
BootCommand: b.config.BootCommand,
|
BootCommand: b.config.FlatBootCommand(),
|
||||||
VMName: b.config.VMName,
|
VMName: b.config.VMName,
|
||||||
Ctx: b.config.ctx,
|
Ctx: b.config.ctx,
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
||||||
"github.com/hashicorp/packer/common"
|
"github.com/hashicorp/packer/common"
|
||||||
|
"github.com/hashicorp/packer/common/boot_command"
|
||||||
"github.com/hashicorp/packer/helper/config"
|
"github.com/hashicorp/packer/helper/config"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
"github.com/hashicorp/packer/template/interpolate"
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
|
@ -16,6 +17,7 @@ type Config struct {
|
||||||
common.PackerConfig `mapstructure:",squash"`
|
common.PackerConfig `mapstructure:",squash"`
|
||||||
common.HTTPConfig `mapstructure:",squash"`
|
common.HTTPConfig `mapstructure:",squash"`
|
||||||
common.FloppyConfig `mapstructure:",squash"`
|
common.FloppyConfig `mapstructure:",squash"`
|
||||||
|
bootcommand.VNCConfig `mapstructure:",squash"`
|
||||||
vmwcommon.DriverConfig `mapstructure:",squash"`
|
vmwcommon.DriverConfig `mapstructure:",squash"`
|
||||||
vmwcommon.OutputConfig `mapstructure:",squash"`
|
vmwcommon.OutputConfig `mapstructure:",squash"`
|
||||||
vmwcommon.RunConfig `mapstructure:",squash"`
|
vmwcommon.RunConfig `mapstructure:",squash"`
|
||||||
|
@ -65,6 +67,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||||
errs = packer.MultiErrorAppend(errs, c.ToolsConfig.Prepare(&c.ctx)...)
|
errs = packer.MultiErrorAppend(errs, c.ToolsConfig.Prepare(&c.ctx)...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.VMXConfig.Prepare(&c.ctx)...)
|
errs = packer.MultiErrorAppend(errs, c.VMXConfig.Prepare(&c.ctx)...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(&c.ctx)...)
|
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(&c.ctx)...)
|
||||||
|
errs = packer.MultiErrorAppend(errs, c.VNCConfig.Prepare(&c.ctx)...)
|
||||||
|
|
||||||
if c.SourcePath == "" {
|
if c.SourcePath == "" {
|
||||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is blank, but is required"))
|
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is blank, but is required"))
|
||||||
|
|
|
@ -84,12 +84,6 @@ type waitExpression struct {
|
||||||
// Do waits the amount of time described by the expression. It is cancellable
|
// Do waits the amount of time described by the expression. It is cancellable
|
||||||
// through the context.
|
// through the context.
|
||||||
func (w *waitExpression) Do(ctx context.Context, _ BCDriver) error {
|
func (w *waitExpression) Do(ctx context.Context, _ BCDriver) error {
|
||||||
/*
|
|
||||||
// do I want this to not parse or to error?
|
|
||||||
if w.d < 0 {
|
|
||||||
panic("Was not expecting negative wait duration.")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
log.Printf("[INFO] Waiting %s", w.d)
|
log.Printf("[INFO] Waiting %s", w.d)
|
||||||
select {
|
select {
|
||||||
case <-time.After(w.d):
|
case <-time.After(w.d):
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package bootcommand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
RawBootWait string `mapstructure:"boot_wait"`
|
||||||
|
BootCommand []string `mapstructure:"boot_command"`
|
||||||
|
|
||||||
|
BootWait time.Duration ``
|
||||||
|
}
|
||||||
|
|
||||||
|
type VNCConfig struct {
|
||||||
|
Config
|
||||||
|
DisableVNC bool `mapstructure:"disable_vnc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) Prepare(ctx *interpolate.Context) (errs []error) {
|
||||||
|
if c.RawBootWait == "" {
|
||||||
|
c.RawBootWait = "10s"
|
||||||
|
}
|
||||||
|
if c.RawBootWait != "" {
|
||||||
|
bw, err := time.ParseDuration(c.RawBootWait)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(
|
||||||
|
errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
|
||||||
|
} else {
|
||||||
|
c.BootWait = bw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) FlatBootCommand() string {
|
||||||
|
return strings.Join(c.BootCommand, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *VNCConfig) Prepare(ctx *interpolate.Context) (errs []error) {
|
||||||
|
if len(c.BootCommand) > 0 && c.DisableVNC {
|
||||||
|
errs = append(errs,
|
||||||
|
fmt.Errorf("A boot command cannot be used when vnc is disabled."))
|
||||||
|
}
|
||||||
|
errs = append(errs, c.Config.Prepare(ctx)...)
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package bootcommand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfigPrepare(t *testing.T) {
|
||||||
|
var c *Config
|
||||||
|
|
||||||
|
// Test a default boot_wait
|
||||||
|
c = new(Config)
|
||||||
|
c.RawBootWait = ""
|
||||||
|
errs := c.Prepare(&interpolate.Context{})
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("bad: %#v", errs)
|
||||||
|
}
|
||||||
|
if c.RawBootWait != "10s" {
|
||||||
|
t.Fatalf("bad value: %s", c.RawBootWait)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with a bad boot_wait
|
||||||
|
c = new(Config)
|
||||||
|
c.RawBootWait = "this is not good"
|
||||||
|
errs = c.Prepare(&interpolate.Context{})
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatal("should error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with a good one
|
||||||
|
c = new(Config)
|
||||||
|
c.RawBootWait = "5s"
|
||||||
|
errs = c.Prepare(&interpolate.Context{})
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("bad: %#v", errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVNCConfigPrepare(t *testing.T) {
|
||||||
|
var c *VNCConfig
|
||||||
|
|
||||||
|
// Test with a boot command
|
||||||
|
c = new(VNCConfig)
|
||||||
|
c.BootCommand = []string{"a", "b"}
|
||||||
|
errs := c.Prepare(&interpolate.Context{})
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("bad: %#v", errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with disabled vnc
|
||||||
|
c.DisableVNC = true
|
||||||
|
errs = c.Prepare(&interpolate.Context{})
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatal("should error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test no boot command with no vnc
|
||||||
|
c = new(VNCConfig)
|
||||||
|
c.DisableVNC = true
|
||||||
|
errs = c.Prepare(&interpolate.Context{})
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("bad: %#v", errs)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue