Refactoring to work with upstream packer changes around templates and SSH connect.
Signed-off-by: Rob Dobson <rob.dobson@citrix.com>
This commit is contained in:
parent
274d86cdc6
commit
351fdbba9d
@ -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))
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user