From 3e76547bff6edd6a84632560401461a77c70cf06 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 27 May 2015 13:39:43 -0700 Subject: [PATCH] bulder/qemu: convert interpolation --- builder/qemu/builder.go | 95 +++++-------------------- builder/qemu/ssh.go | 2 +- builder/qemu/step_boot_wait.go | 2 +- builder/qemu/step_configure_vnc.go | 2 +- builder/qemu/step_copy_disk.go | 2 +- builder/qemu/step_create_disk.go | 2 +- builder/qemu/step_forward_ssh.go | 2 +- builder/qemu/step_http_server.go | 2 +- builder/qemu/step_prepare_output_dir.go | 4 +- builder/qemu/step_resize_disk.go | 2 +- builder/qemu/step_run.go | 12 ++-- builder/qemu/step_shutdown.go | 2 +- builder/qemu/step_type_boot_command.go | 15 ++-- 13 files changed, 43 insertions(+), 101 deletions(-) diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index e3bc6e4a1..9b4abb437 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -13,7 +13,9 @@ import ( "github.com/mitchellh/multistep" "github.com/mitchellh/packer/common" commonssh "github.com/mitchellh/packer/common/ssh" + "github.com/mitchellh/packer/helper/config" "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) const BuilderId = "transcend.qemu" @@ -65,11 +67,11 @@ var diskCache = map[string]bool{ } type Builder struct { - config config + config Config runner multistep.Runner } -type config struct { +type Config struct { common.PackerConfig `mapstructure:",squash"` Accelerator string `mapstructure:"accelerator"` @@ -114,25 +116,26 @@ type config struct { bootWait time.Duration `` shutdownTimeout time.Duration `` sshWaitTimeout time.Duration `` - tpl *packer.ConfigTemplate + ctx interpolate.Context } func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { - md, err := common.DecodeConfig(&b.config, raws...) + err := config.Decode(&b.config, &config.DecodeOpts{ + Interpolate: true, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{ + "boot_command", + "qemuargs", + }, + }, + }, raws...) if err != nil { return nil, err } + + var errs *packer.MultiError warnings := make([]string, 0) - b.config.tpl, err = packer.NewConfigTemplate() - if err != nil { - return nil, err - } - b.config.tpl.UserVars = b.config.PackerUserVars - - // Accumulate any errors - errs := common.CheckUnusedConfig(md) - if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } @@ -189,15 +192,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.config.VNCPortMax = 6000 } - for i, args := range b.config.QemuArgs { - for j, arg := range args { - if err := b.config.tpl.Validate(arg); err != nil { - errs = packer.MultiErrorAppend(errs, - fmt.Errorf("Error processing qemu-system_x86-64[%d][%d]: %s", i, j, err)) - } - } - } - if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } @@ -218,63 +212,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.config.DiskInterface = "virtio" } - // Errors - templates := map[string]*string{ - "http_directory": &b.config.HTTPDir, - "iso_checksum": &b.config.ISOChecksum, - "iso_checksum_type": &b.config.ISOChecksumType, - "iso_url": &b.config.RawSingleISOUrl, - "output_directory": &b.config.OutputDir, - "shutdown_command": &b.config.ShutdownCommand, - "ssh_key_path": &b.config.SSHKeyPath, - "ssh_password": &b.config.SSHPassword, - "ssh_username": &b.config.SSHUser, - "vm_name": &b.config.VMName, - "format": &b.config.Format, - "boot_wait": &b.config.RawBootWait, - "shutdown_timeout": &b.config.RawShutdownTimeout, - "ssh_wait_timeout": &b.config.RawSSHWaitTimeout, - "accelerator": &b.config.Accelerator, - "machine_type": &b.config.MachineType, - "net_device": &b.config.NetDevice, - "disk_interface": &b.config.DiskInterface, - } - - for n, ptr := range templates { - var err error - *ptr, err = b.config.tpl.Process(*ptr, nil) - if err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } - - for i, url := range b.config.ISOUrls { - var err error - b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) - if err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) - } - } - - for i, command := range b.config.BootCommand { - if err := b.config.tpl.Validate(command); err != nil { - errs = packer.MultiErrorAppend(errs, - fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) - } - } - - for i, file := range b.config.FloppyFiles { - var err error - b.config.FloppyFiles[i], err = b.config.tpl.Process(file, nil) - if err != nil { - errs = packer.MultiErrorAppend(errs, - fmt.Errorf("Error processing floppy_files[%d]: %s", - i, err)) - } - } - if !(b.config.Format == "qcow2" || b.config.Format == "raw") { errs = packer.MultiErrorAppend( errs, errors.New("invalid format, only 'qcow2' or 'raw' are allowed")) diff --git a/builder/qemu/ssh.go b/builder/qemu/ssh.go index de7858166..dfd87ee20 100644 --- a/builder/qemu/ssh.go +++ b/builder/qemu/ssh.go @@ -15,7 +15,7 @@ func sshAddress(state multistep.StateBag) (string, error) { } func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) auth := []gossh.AuthMethod{ gossh.Password(config.SSHPassword), diff --git a/builder/qemu/step_boot_wait.go b/builder/qemu/step_boot_wait.go index 46a48dcbc..8557900a5 100644 --- a/builder/qemu/step_boot_wait.go +++ b/builder/qemu/step_boot_wait.go @@ -11,7 +11,7 @@ import ( type stepBootWait struct{} func (s *stepBootWait) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) if int64(config.bootWait) > 0 { diff --git a/builder/qemu/step_configure_vnc.go b/builder/qemu/step_configure_vnc.go index 097271b51..be452620d 100644 --- a/builder/qemu/step_configure_vnc.go +++ b/builder/qemu/step_configure_vnc.go @@ -20,7 +20,7 @@ import ( type stepConfigureVNC struct{} func (stepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) // Find an open VNC port. Note that this can still fail later on diff --git a/builder/qemu/step_copy_disk.go b/builder/qemu/step_copy_disk.go index 54c3084ac..6afb70cb0 100644 --- a/builder/qemu/step_copy_disk.go +++ b/builder/qemu/step_copy_disk.go @@ -14,7 +14,7 @@ import ( type stepCopyDisk struct{} func (s *stepCopyDisk) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) isoPath := state.Get("iso_path").(string) ui := state.Get("ui").(packer.Ui) diff --git a/builder/qemu/step_create_disk.go b/builder/qemu/step_create_disk.go index 986df1d2b..a1b5623a4 100644 --- a/builder/qemu/step_create_disk.go +++ b/builder/qemu/step_create_disk.go @@ -13,7 +13,7 @@ import ( type stepCreateDisk struct{} func (s *stepCreateDisk) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) name := config.VMName + "." + strings.ToLower(config.Format) diff --git a/builder/qemu/step_forward_ssh.go b/builder/qemu/step_forward_ssh.go index 3b84d26c1..c88d5623d 100644 --- a/builder/qemu/step_forward_ssh.go +++ b/builder/qemu/step_forward_ssh.go @@ -19,7 +19,7 @@ import ( type stepForwardSSH struct{} func (s *stepForwardSSH) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) log.Printf("Looking for available SSH port between %d and %d", config.SSHHostPortMin, config.SSHHostPortMax) diff --git a/builder/qemu/step_http_server.go b/builder/qemu/step_http_server.go index 831253853..a5d784ec2 100644 --- a/builder/qemu/step_http_server.go +++ b/builder/qemu/step_http_server.go @@ -25,7 +25,7 @@ type stepHTTPServer struct { } func (s *stepHTTPServer) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) var httpPort uint = 0 diff --git a/builder/qemu/step_prepare_output_dir.go b/builder/qemu/step_prepare_output_dir.go index 43320399a..0f3bd1278 100644 --- a/builder/qemu/step_prepare_output_dir.go +++ b/builder/qemu/step_prepare_output_dir.go @@ -11,7 +11,7 @@ import ( type stepPrepareOutputDir struct{} func (stepPrepareOutputDir) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) if _, err := os.Stat(config.OutputDir); err == nil && config.PackerForce { @@ -32,7 +32,7 @@ func (stepPrepareOutputDir) Cleanup(state multistep.StateBag) { _, halted := state.GetOk(multistep.StateHalted) if cancelled || halted { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) ui.Say("Deleting output directory...") diff --git a/builder/qemu/step_resize_disk.go b/builder/qemu/step_resize_disk.go index 4e8536c32..58e405747 100644 --- a/builder/qemu/step_resize_disk.go +++ b/builder/qemu/step_resize_disk.go @@ -13,7 +13,7 @@ import ( type stepResizeDisk struct{} func (s *stepResizeDisk) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) path := filepath.Join(config.OutputDir, fmt.Sprintf("%s.%s", config.VMName, diff --git a/builder/qemu/step_run.go b/builder/qemu/step_run.go index 3f900d651..aa13a1076 100644 --- a/builder/qemu/step_run.go +++ b/builder/qemu/step_run.go @@ -8,6 +8,7 @@ import ( "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) // stepRun runs the virtual machine @@ -56,7 +57,7 @@ func (s *stepRun) Cleanup(state multistep.StateBag) { } func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error) { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) isoPath := state.Get("iso_path").(string) vncPort := state.Get("vnc_port").(uint) sshHostPort := state.Get("sshHostPort").(uint) @@ -109,14 +110,15 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error ui.Say("Overriding defaults Qemu arguments with QemuArgs...") httpPort := state.Get("http_port").(uint) - tplData := qemuArgsTemplateData{ + ctx := config.ctx + ctx.Data = qemuArgsTemplateData{ "10.0.2.2", httpPort, config.HTTPDir, config.OutputDir, config.VMName, } - newQemuArgs, err := processArgs(config.QemuArgs, config.tpl, &tplData) + newQemuArgs, err := processArgs(config.QemuArgs, &ctx) if err != nil { return nil, err } @@ -160,7 +162,7 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error return outArgs, nil } -func processArgs(args [][]string, tpl *packer.ConfigTemplate, tplData *qemuArgsTemplateData) ([][]string, error) { +func processArgs(args [][]string, ctx *interpolate.Context) ([][]string, error) { var err error if args == nil { @@ -172,7 +174,7 @@ func processArgs(args [][]string, tpl *packer.ConfigTemplate, tplData *qemuArgsT parms := make([]string, len(rowArgs)) newArgs[argsIdx] = parms for i, parm := range rowArgs { - parms[i], err = tpl.Process(parm, &tplData) + parms[i], err = interpolate.Render(parm, ctx) if err != nil { return nil, err } diff --git a/builder/qemu/step_shutdown.go b/builder/qemu/step_shutdown.go index a225496b2..127dcff12 100644 --- a/builder/qemu/step_shutdown.go +++ b/builder/qemu/step_shutdown.go @@ -24,7 +24,7 @@ type stepShutdown struct{} func (s *stepShutdown) Run(state multistep.StateBag) multistep.StepAction { comm := state.Get("communicator").(packer.Communicator) - config := state.Get("config").(*config) + config := state.Get("config").(*Config) driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) diff --git a/builder/qemu/step_type_boot_command.go b/builder/qemu/step_type_boot_command.go index 6416e0ea1..e42903f55 100644 --- a/builder/qemu/step_type_boot_command.go +++ b/builder/qemu/step_type_boot_command.go @@ -2,15 +2,17 @@ package qemu import ( "fmt" - "github.com/mitchellh/go-vnc" - "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/packer" "log" "net" "strings" "time" "unicode" "unicode/utf8" + + "github.com/mitchellh/go-vnc" + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" ) const KeyLeftShift uint32 = 0xFFE1 @@ -34,7 +36,7 @@ type bootCommandTemplateData struct { type stepTypeBootCommand struct{} func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) + config := state.Get("config").(*Config) httpPort := state.Get("http_port").(uint) ui := state.Get("ui").(packer.Ui) vncPort := state.Get("vnc_port").(uint) @@ -61,7 +63,8 @@ func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction log.Printf("Connected to VNC desktop: %s", c.DesktopName) - tplData := &bootCommandTemplateData{ + ctx := config.ctx + ctx.Data = &bootCommandTemplateData{ "10.0.2.2", httpPort, config.VMName, @@ -69,7 +72,7 @@ func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction ui.Say("Typing the boot command over VNC...") for _, command := range config.BootCommand { - command, err := config.tpl.Process(command, tplData) + command, err := interpolate.Render(command, &ctx) if err != nil { err := fmt.Errorf("Error preparing boot command: %s", err) state.Put("error", err)