flatten boot command config and implement for vmware
This commit is contained in:
parent
84894ca459
commit
408eba88ad
|
@ -2,30 +2,20 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
type RunConfig struct {
|
||||
Headless bool `mapstructure:"headless"`
|
||||
RawBootWait string `mapstructure:"boot_wait"`
|
||||
DisableVNC bool `mapstructure:"disable_vnc"`
|
||||
BootCommand []string `mapstructure:"boot_command"`
|
||||
Headless bool `mapstructure:"headless"`
|
||||
|
||||
VNCBindAddress string `mapstructure:"vnc_bind_address"`
|
||||
VNCPortMin uint `mapstructure:"vnc_port_min"`
|
||||
VNCPortMax uint `mapstructure:"vnc_port_max"`
|
||||
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 {
|
||||
c.VNCPortMin = 5900
|
||||
}
|
||||
|
@ -38,25 +28,9 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
|||
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 {
|
||||
errs = append(
|
||||
errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max"))
|
||||
errs = append(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:
|
||||
// <nothing>
|
||||
type StepTypeBootCommand struct {
|
||||
BootCommand []string
|
||||
BootCommand string
|
||||
VNCEnabled bool
|
||||
BootWait time.Duration
|
||||
VMName string
|
||||
|
@ -118,34 +118,32 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag)
|
|||
d := bootcommand.NewVNCDriver(c)
|
||||
|
||||
ui.Say("Typing the boot command over VNC...")
|
||||
for i, command := range s.BootCommand {
|
||||
command, err := interpolate.Render(command, &s.Ctx)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error preparing boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
command, err := interpolate.Render(s.BootCommand, &s.Ctx)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error preparing boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
seq, err := bootcommand.GenerateExpressionSequence(command)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error generating boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
seq, err := bootcommand.GenerateExpressionSequence(command)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error generating boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err := seq.Do(ctx, d); err != nil {
|
||||
err := fmt.Errorf("Error running boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if pauseFn != nil {
|
||||
pauseFn(multistep.DebugLocationAfterRun, fmt.Sprintf("boot_command[%d]: %s", i, command), state)
|
||||
}
|
||||
if err := seq.Do(ctx, d); err != nil {
|
||||
err := fmt.Errorf("Error running boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if pauseFn != nil {
|
||||
pauseFn(multistep.DebugLocationAfterRun,
|
||||
fmt.Sprintf("boot_command: %s", command), state)
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/boot_command"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
@ -30,6 +31,7 @@ type Config struct {
|
|||
common.HTTPConfig `mapstructure:",squash"`
|
||||
common.ISOConfig `mapstructure:",squash"`
|
||||
common.FloppyConfig `mapstructure:",squash"`
|
||||
bootcommand.VNCConfig `mapstructure:",squash"`
|
||||
vmwcommon.DriverConfig `mapstructure:",squash"`
|
||||
vmwcommon.OutputConfig `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.VMXConfig.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 == "" {
|
||||
b.config.DiskName = "disk"
|
||||
|
@ -325,7 +328,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
&vmwcommon.StepTypeBootCommand{
|
||||
BootWait: b.config.BootWait,
|
||||
VNCEnabled: !b.config.DisableVNC,
|
||||
BootCommand: b.config.BootCommand,
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
},
|
||||
|
|
|
@ -93,7 +93,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
&vmwcommon.StepTypeBootCommand{
|
||||
BootWait: b.config.BootWait,
|
||||
VNCEnabled: !b.config.DisableVNC,
|
||||
BootCommand: b.config.BootCommand,
|
||||
BootCommand: b.config.FlatBootCommand(),
|
||||
VMName: b.config.VMName,
|
||||
Ctx: b.config.ctx,
|
||||
},
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/common/boot_command"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
|
@ -16,6 +17,7 @@ type Config struct {
|
|||
common.PackerConfig `mapstructure:",squash"`
|
||||
common.HTTPConfig `mapstructure:",squash"`
|
||||
common.FloppyConfig `mapstructure:",squash"`
|
||||
bootcommand.VNCConfig `mapstructure:",squash"`
|
||||
vmwcommon.DriverConfig `mapstructure:",squash"`
|
||||
vmwcommon.OutputConfig `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.VMXConfig.Prepare(&c.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(&c.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, c.VNCConfig.Prepare(&c.ctx)...)
|
||||
|
||||
if c.SourcePath == "" {
|
||||
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
|
||||
// through the context.
|
||||
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)
|
||||
select {
|
||||
case <-time.After(w.d):
|
||||
|
|
|
@ -109,8 +109,8 @@ func Test_negativeWait(t *testing.T) {
|
|||
|
||||
/*
|
||||
gL := toIfaceSlice(got)
|
||||
for _, g := range gL {
|
||||
assert.Equal(t, tt.out, g.(*specialExpression).String())
|
||||
}
|
||||
for _, g := range gL {
|
||||
assert.Equal(t, tt.out, g.(*specialExpression).String())
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -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