From 351fdbba9de833051b9541065a3a490a9a404726 Mon Sep 17 00:00:00 2001 From: Rob Dobson Date: Fri, 19 Jun 2015 18:33:11 +0100 Subject: [PATCH] Refactoring to work with upstream packer changes around templates and SSH connect. Signed-off-by: Rob Dobson --- builder/xenserver/common/common_config.go | 56 +++---------------- builder/xenserver/common/ssh.go | 50 ++++++++++------- .../common/step_type_boot_command.go | 7 ++- builder/xenserver/iso/builder.go | 56 +++++++++---------- builder/xenserver/xva/builder.go | 54 ++++++++---------- 5 files changed, 95 insertions(+), 128 deletions(-) diff --git a/builder/xenserver/common/common_config.go b/builder/xenserver/common/common_config.go index 699b1bb..0c644c0 100644 --- a/builder/xenserver/common/common_config.go +++ b/builder/xenserver/common/common_config.go @@ -9,7 +9,7 @@ import ( "github.com/mitchellh/multistep" "github.com/mitchellh/packer/common" commonssh "github.com/mitchellh/packer/common/ssh" - "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" xsclient "github.com/xenserver/go-xenserver-client" ) @@ -41,10 +41,12 @@ type CommonConfig struct { // SSHHostPortMin uint `mapstructure:"ssh_host_port_min"` // SSHHostPortMax uint `mapstructure:"ssh_host_port_max"` - SSHKeyPath string `mapstructure:"ssh_key_path"` - SSHPassword string `mapstructure:"ssh_password"` - SSHPort uint `mapstructure:"ssh_port"` - SSHUser string `mapstructure:"ssh_username"` + SSHKeyPath string `mapstructure:"ssh_key_path"` + SSHPassword string `mapstructure:"ssh_password"` + SSHPort uint `mapstructure:"ssh_port"` + SSHUser string `mapstructure:"ssh_username"` + SSHConfig `mapstructure:",squash"` + RawSSHWaitTimeout string `mapstructure:"ssh_wait_timeout"` SSHWaitTimeout time.Duration @@ -54,8 +56,9 @@ type CommonConfig struct { IPGetter string `mapstructure:"ip_getter"` } -func (c *CommonConfig) Prepare(t *packer.ConfigTemplate, pc *common.PackerConfig) []error { +func (c *CommonConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig) []error { var err error + var errs []error // Set default values @@ -129,40 +132,6 @@ func (c *CommonConfig) Prepare(t *packer.ConfigTemplate, pc *common.PackerConfig c.IPGetter = "auto" } - // Template substitution - - templates := map[string]*string{ - "remote_username": &c.Username, - "remote_password": &c.Password, - "remote_host": &c.HostIp, - "vm_name": &c.VMName, - "vm_description": &c.VMDescription, - "sr_name": &c.SrName, - "shutdown_command": &c.ShutdownCommand, - "boot_wait": &c.RawBootWait, - "tools_iso_name": &c.ToolsIsoName, - "http_directory": &c.HTTPDir, - "ssh_key_path": &c.SSHKeyPath, - "ssh_password": &c.SSHPassword, - "ssh_username": &c.SSHUser, - "ssh_wait_timeout": &c.RawSSHWaitTimeout, - "output_directory": &c.OutputDir, - "format": &c.Format, - "keep_vm": &c.KeepVM, - "ip_getter": &c.IPGetter, - } - for i := range c.FloppyFiles { - templates[fmt.Sprintf("floppy_files[%d]", i)] = &c.FloppyFiles[i] - } - - errs := make([]error, 0) - for n, ptr := range templates { - *ptr, err = t.Process(*ptr, nil) - if err != nil { - errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } - // Validation if c.Username == "" { @@ -190,13 +159,6 @@ func (c *CommonConfig) Prepare(t *packer.ConfigTemplate, pc *common.PackerConfig errs = append(errs, fmt.Errorf("Failed to parse boot_wait: %s", err)) } - for i, command := range c.BootCommand { - if err := t.Validate(command); err != nil { - errs = append(errs, - fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) - } - } - if c.SSHKeyPath != "" { if _, err := os.Stat(c.SSHKeyPath); err != nil { errs = append(errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) diff --git a/builder/xenserver/common/ssh.go b/builder/xenserver/common/ssh.go index 77e03e6..6ba407a 100644 --- a/builder/xenserver/common/ssh.go +++ b/builder/xenserver/common/ssh.go @@ -2,11 +2,11 @@ package common import ( "bytes" - gossh "code.google.com/p/go.crypto/ssh" "fmt" "github.com/mitchellh/multistep" commonssh "github.com/mitchellh/packer/common/ssh" "github.com/mitchellh/packer/communicator/ssh" + gossh "golang.org/x/crypto/ssh" "io" "log" "net" @@ -28,27 +28,38 @@ func SSHLocalAddress(state multistep.StateBag) (string, error) { return conn_str, nil } -func SSHConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { - config := state.Get("commonconfig").(CommonConfig) - auth := []gossh.AuthMethod{ - gossh.Password(config.SSHPassword), - gossh.KeyboardInteractive( - ssh.PasswordKeyboardInteractive(config.SSHPassword)), - } +func SSHPort(state multistep.StateBag) (int, error) { + sshHostPort := state.Get("local_ssh_port").(uint) + return int(sshHostPort), nil +} - if config.SSHKeyPath != "" { - signer, err := commonssh.FileSigner(config.SSHKeyPath) - if err != nil { - return nil, err +func CommHost(state multistep.StateBag) (string, error) { + return "127.0.0.1", nil +} + +func SSHConfigFunc(config SSHConfig) func(multistep.StateBag) (*gossh.ClientConfig, error) { + return func(state multistep.StateBag) (*gossh.ClientConfig, error) { + config := state.Get("commonconfig").(CommonConfig) + auth := []gossh.AuthMethod{ + gossh.Password(config.SSHPassword), + gossh.KeyboardInteractive( + ssh.PasswordKeyboardInteractive(config.SSHPassword)), } - auth = append(auth, gossh.PublicKeys(signer)) - } + if config.SSHKeyPath != "" { + signer, err := commonssh.FileSigner(config.SSHKeyPath) + if err != nil { + return nil, err + } - return &gossh.ClientConfig{ - User: config.SSHUser, - Auth: auth, - }, nil + auth = append(auth, gossh.PublicKeys(signer)) + } + + return &gossh.ClientConfig{ + User: config.SSHUser, + Auth: auth, + }, nil + } } func doExecuteSSHCmd(cmd, target string, config *gossh.ClientConfig) (stdout string, err error) { @@ -87,11 +98,12 @@ func ExecuteHostSSHCmd(state multistep.StateBag, cmd string) (stdout string, err } func ExecuteGuestSSHCmd(state multistep.StateBag, cmd string) (stdout string, err error) { + config := state.Get("commonconfig").(CommonConfig) localAddress, err := SSHLocalAddress(state) if err != nil { return } - sshConfig, err := SSHConfig(state) + sshConfig, err := SSHConfigFunc(config.SSHConfig)(state) if err != nil { return } diff --git a/builder/xenserver/common/step_type_boot_command.go b/builder/xenserver/common/step_type_boot_command.go index e6f35a2..a9207ec 100644 --- a/builder/xenserver/common/step_type_boot_command.go +++ b/builder/xenserver/common/step_type_boot_command.go @@ -7,6 +7,7 @@ import ( "github.com/mitchellh/go-vnc" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" "log" "net" "strings" @@ -24,7 +25,7 @@ type bootCommandTemplateData struct { } type StepTypeBootCommand struct { - Tpl *packer.ConfigTemplate + Ctx interpolate.Context } func (self *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { @@ -78,7 +79,7 @@ func (self *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAct localIp := strings.Split(envVar, " ")[0] ui.Message(fmt.Sprintf("Found local IP: %s", localIp)) - tplData := &bootCommandTemplateData{ + self.Ctx.Data = &bootCommandTemplateData{ config.VMName, localIp, http_port, @@ -87,7 +88,7 @@ func (self *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAct ui.Say("Typing boot commands over VNC...") for _, command := range config.BootCommand { - command, err := self.Tpl.Process(command, tplData) + command, err := interpolate.Render(command, &self.Ctx) if err != nil { err := fmt.Errorf("Error preparing boot command: %s", err) state.Put("error", err) diff --git a/builder/xenserver/iso/builder.go b/builder/xenserver/iso/builder.go index f227745..f21ca18 100644 --- a/builder/xenserver/iso/builder.go +++ b/builder/xenserver/iso/builder.go @@ -10,7 +10,10 @@ import ( "github.com/mitchellh/multistep" "github.com/mitchellh/packer/common" + "github.com/mitchellh/packer/helper/communicator" + hconfig "github.com/mitchellh/packer/helper/config" "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common" xsclient "github.com/xenserver/go-xenserver-client" ) @@ -34,7 +37,7 @@ type config struct { RawInstallTimeout string `mapstructure:"install_timeout"` InstallTimeout time.Duration `` - tpl *packer.ConfigTemplate + ctx interpolate.Context } type Builder struct { @@ -44,20 +47,23 @@ type Builder struct { func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error) { - md, err := common.DecodeConfig(&self.config, raws...) + var errs *packer.MultiError + + err := hconfig.Decode(&self.config, &hconfig.DecodeOpts{ + Interpolate: true, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{ + "boot_command", + }, + }, + }, raws...) + if err != nil { - return nil, err + packer.MultiErrorAppend(errs, err) } - self.config.tpl, err = packer.NewConfigTemplate() - if err != nil { - return nil, err - } - self.config.tpl.UserVars = self.config.PackerUserVars - - errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend( - errs, self.config.CommonConfig.Prepare(self.config.tpl, &self.config.PackerConfig)...) + errs, self.config.CommonConfig.Prepare(&self.config.ctx, &self.config.PackerConfig)...) // Set default values @@ -103,14 +109,6 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error templates[fmt.Sprintf("iso_urls[%d]", i)] = &self.config.ISOUrls[i] } - for n, ptr := range templates { - var err error - *ptr, err = self.config.tpl.Process(*ptr, nil) - if err != nil { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } - // Validation self.config.InstallTimeout, err = time.ParseDuration(self.config.RawInstallTimeout) @@ -285,7 +283,7 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa }, new(xscommon.StepBootWait), &xscommon.StepTypeBootCommand{ - Tpl: self.config.tpl, + Ctx: self.config.ctx, }, &xscommon.StepWaitForIP{ Chan: httpReqChan, @@ -298,10 +296,11 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa HostPortMax: self.config.HostPortMax, ResultKey: "local_ssh_port", }, - &common.StepConnectSSH{ - SSHAddress: xscommon.SSHLocalAddress, - SSHConfig: xscommon.SSHConfig, - SSHWaitTimeout: self.config.SSHWaitTimeout, + &communicator.StepConnect{ + Config: &self.config.SSHConfig.Comm, + Host: xscommon.CommHost, + SSHConfig: xscommon.SSHConfigFunc(self.config.CommonConfig.SSHConfig), + SSHPort: xscommon.SSHPort, }, new(xscommon.StepShutdown), &xscommon.StepDetachVdi{ @@ -312,10 +311,11 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa }, new(xscommon.StepStartVmPaused), new(xscommon.StepBootWait), - &common.StepConnectSSH{ - SSHAddress: xscommon.SSHLocalAddress, - SSHConfig: xscommon.SSHConfig, - SSHWaitTimeout: self.config.SSHWaitTimeout, + &communicator.StepConnectSSH{ + Config: &self.config.SSHConfig.Comm, + Host: xscommon.CommHost, + SSHConfig: xscommon.SSHConfigFunc(self.config.CommonConfig.SSHConfig), + SSHPort: xscommon.SSHPort, }, new(common.StepProvision), new(xscommon.StepShutdown), diff --git a/builder/xenserver/xva/builder.go b/builder/xenserver/xva/builder.go index 9375619..fe11f35 100644 --- a/builder/xenserver/xva/builder.go +++ b/builder/xenserver/xva/builder.go @@ -8,7 +8,10 @@ import ( "github.com/mitchellh/multistep" "github.com/mitchellh/packer/common" + "github.com/mitchellh/packer/helper/communicator" + hconfig "github.com/mitchellh/packer/helper/config" "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template/interpolate" xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common" xsclient "github.com/xenserver/go-xenserver-client" ) @@ -22,7 +25,7 @@ type config struct { PlatformArgs map[string]string `mapstructure:"platform_args"` - tpl *packer.ConfigTemplate + ctx interpolate.Context } type Builder struct { @@ -32,20 +35,23 @@ type Builder struct { func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error) { - md, err := common.DecodeConfig(&self.config, raws...) + var errs *packer.MultiError + + err := hconfig.Decode(&self.config, &hconfig.DecodeOpts{ + Interpolate: true, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{ + "boot_command", + }, + }, + }, raws...) + if err != nil { - return nil, err + packer.MultiErrorAppend(errs, err) } - self.config.tpl, err = packer.NewConfigTemplate() - if err != nil { - return nil, err - } - self.config.tpl.UserVars = self.config.PackerUserVars - - errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend( - errs, self.config.CommonConfig.Prepare(self.config.tpl, &self.config.PackerConfig)...) + errs, self.config.CommonConfig.Prepare(&self.config.ctx, &self.config.PackerConfig)...) // Set default values @@ -64,21 +70,6 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error self.config.PlatformArgs = pargs } - // Template substitution - - templates := map[string]*string{ - "source_path": &self.config.SourcePath, - "network_name": &self.config.NetworkName, - } - - for n, ptr := range templates { - var err error - *ptr, err = self.config.tpl.Process(*ptr, nil) - if err != nil { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing %s: %s", n, err)) - } - } - // Validation if self.config.SourcePath == "" { @@ -162,7 +153,7 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa }, new(xscommon.StepBootWait), &xscommon.StepTypeBootCommand{ - Tpl: self.config.tpl, + Ctx: self.config.ctx, }, &xscommon.StepWaitForIP{ Chan: httpReqChan, @@ -175,10 +166,11 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa HostPortMax: self.config.HostPortMax, ResultKey: "local_ssh_port", }, - &common.StepConnectSSH{ - SSHAddress: xscommon.SSHLocalAddress, - SSHConfig: xscommon.SSHConfig, - SSHWaitTimeout: self.config.SSHWaitTimeout, + &communicator.StepConnect{ + Config: &self.config.SSHConfig.Comm, + Host: xscommon.CommHost, + SSHConfig: xscommon.SSHConfigFunc(self.config.CommonConfig.SSHConfig), + SSHPort: xscommon.SSHPort, }, new(common.StepProvision), new(xscommon.StepShutdown),