builder/parallels/iso: new interpolation

This commit is contained in:
Mitchell Hashimoto 2015-05-27 13:49:31 -07:00
parent 3e76547bff
commit 76c2d2cb0e
15 changed files with 80 additions and 210 deletions

View File

@ -1,9 +1,7 @@
package common
import (
"fmt"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
// FloppyConfig is configuration related to created floppy disks and attaching
@ -12,20 +10,10 @@ type FloppyConfig struct {
FloppyFiles []string `mapstructure:"floppy_files"`
}
func (c *FloppyConfig) Prepare(t *packer.ConfigTemplate) []error {
func (c *FloppyConfig) Prepare(ctx *interpolate.Context) []error {
if c.FloppyFiles == nil {
c.FloppyFiles = make([]string, 0)
}
errs := make([]error, 0)
for i, file := range c.FloppyFiles {
var err error
c.FloppyFiles[i], err = t.Process(file, nil)
if err != nil {
errs = append(errs, fmt.Errorf(
"Error processing floppy_files[%d]: %s", i, err))
}
}
return errs
return nil
}

View File

@ -2,33 +2,22 @@ package common
import (
"fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"os"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/template/interpolate"
)
type OutputConfig struct {
OutputDir string `mapstructure:"output_directory"`
}
func (c *OutputConfig) Prepare(t *packer.ConfigTemplate, pc *common.PackerConfig) []error {
func (c *OutputConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig) []error {
if c.OutputDir == "" {
c.OutputDir = fmt.Sprintf("output-%s", pc.PackerBuildName)
}
templates := map[string]*string{
"output_directory": &c.OutputDir,
}
errs := make([]error, 0)
for n, ptr := range templates {
var err error
*ptr, err = t.Process(*ptr, nil)
if err != nil {
errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
var errs []error
if !pc.PackerForce {
if _, err := os.Stat(c.OutputDir); err == nil {
errs = append(errs, fmt.Errorf(

View File

@ -1,28 +1,17 @@
package common
import (
"fmt"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type PrlctlConfig struct {
Prlctl [][]string `mapstructure:"prlctl"`
}
func (c *PrlctlConfig) Prepare(t *packer.ConfigTemplate) []error {
func (c *PrlctlConfig) Prepare(ctx *interpolate.Context) []error {
if c.Prlctl == nil {
c.Prlctl = make([][]string, 0)
}
errs := make([]error, 0)
for i, args := range c.Prlctl {
for j, arg := range args {
if err := t.Validate(arg); err != nil {
errs = append(errs,
fmt.Errorf("Error processing prlctl[%d][%d]: %s", i, j, err))
}
}
}
return errs
return nil
}

View File

@ -1,31 +1,17 @@
package common
import (
"fmt"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type PrlctlVersionConfig struct {
PrlctlVersionFile string `mapstructure:"prlctl_version_file"`
}
func (c *PrlctlVersionConfig) Prepare(t *packer.ConfigTemplate) []error {
func (c *PrlctlVersionConfig) Prepare(ctx *interpolate.Context) []error {
if c.PrlctlVersionFile == "" {
c.PrlctlVersionFile = ".prlctl_version"
}
templates := map[string]*string{
"prlctl_version_file": &c.PrlctlVersionFile,
}
errs := make([]error, 0)
for n, ptr := range templates {
var err error
*ptr, err = t.Process(*ptr, nil)
if err != nil {
errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
return errs
return nil
}

View File

@ -2,8 +2,9 @@ package common
import (
"fmt"
"github.com/mitchellh/packer/packer"
"time"
"github.com/mitchellh/packer/template/interpolate"
)
type RunConfig struct {
@ -13,29 +14,16 @@ type RunConfig struct {
BootWait time.Duration ``
}
func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error {
func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
if c.RawBootWait == "" {
c.RawBootWait = "10s"
}
templates := map[string]*string{
"boot_wait": &c.RawBootWait,
}
errs := make([]error, 0)
for n, ptr := range templates {
var err error
*ptr, err = t.Process(*ptr, nil)
if err != nil {
errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
var err error
c.BootWait, err = time.ParseDuration(c.RawBootWait)
if err != nil {
errs = append(errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
return []error{fmt.Errorf("Failed parsing boot_wait: %s", err)}
}
return errs
return nil
}

View File

@ -2,8 +2,9 @@ package common
import (
"fmt"
"github.com/mitchellh/packer/packer"
"time"
"github.com/mitchellh/packer/template/interpolate"
)
type ShutdownConfig struct {
@ -13,25 +14,12 @@ type ShutdownConfig struct {
ShutdownTimeout time.Duration ``
}
func (c *ShutdownConfig) Prepare(t *packer.ConfigTemplate) []error {
func (c *ShutdownConfig) Prepare(ctx *interpolate.Context) []error {
if c.RawShutdownTimeout == "" {
c.RawShutdownTimeout = "5m"
}
templates := map[string]*string{
"shutdown_command": &c.ShutdownCommand,
"shutdown_timeout": &c.RawShutdownTimeout,
}
errs := make([]error, 0)
for n, ptr := range templates {
var err error
*ptr, err = t.Process(*ptr, nil)
if err != nil {
errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
var errs []error
var err error
c.ShutdownTimeout, err = time.ParseDuration(c.RawShutdownTimeout)
if err != nil {

View File

@ -7,7 +7,7 @@ import (
"time"
commonssh "github.com/mitchellh/packer/common/ssh"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type SSHConfig struct {
@ -20,7 +20,7 @@ type SSHConfig struct {
SSHWaitTimeout time.Duration
}
func (c *SSHConfig) Prepare(t *packer.ConfigTemplate) []error {
func (c *SSHConfig) Prepare(ctx *interpolate.Context) []error {
if c.SSHPort == 0 {
c.SSHPort = 22
}
@ -29,22 +29,7 @@ func (c *SSHConfig) Prepare(t *packer.ConfigTemplate) []error {
c.RawSSHWaitTimeout = "20m"
}
templates := map[string]*string{
"ssh_key_path": &c.SSHKeyPath,
"ssh_password": &c.SSHPassword,
"ssh_username": &c.SSHUser,
"ssh_wait_timeout": &c.RawSSHWaitTimeout,
}
errs := make([]error, 0)
for n, ptr := range templates {
var err error
*ptr, err = t.Process(*ptr, nil)
if err != nil {
errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
var errs []error
if c.SSHKeyPath != "" {
if _, err := os.Stat(c.SSHKeyPath); err != nil {
errs = append(errs, fmt.Errorf("ssh_key_path is invalid: %s", err))

View File

@ -2,9 +2,11 @@ package common
import (
"fmt"
"strings"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"strings"
"github.com/mitchellh/packer/template/interpolate"
)
type commandTemplate struct {
@ -22,7 +24,7 @@ type commandTemplate struct {
// Produces:
type StepPrlctl struct {
Commands [][]string
Tpl *packer.ConfigTemplate
Ctx interpolate.Context
}
func (s *StepPrlctl) Run(state multistep.StateBag) multistep.StepAction {
@ -34,7 +36,7 @@ func (s *StepPrlctl) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Executing custom prlctl commands...")
}
tplData := &commandTemplate{
s.Ctx.Data = &commandTemplate{
Name: vmName,
}
@ -44,7 +46,7 @@ func (s *StepPrlctl) Run(state multistep.StateBag) multistep.StepAction {
for i, arg := range command {
var err error
command[i], err = s.Tpl.Process(arg, tplData)
command[i], err = interpolate.Render(arg, &s.Ctx)
if err != nil {
err := fmt.Errorf("Error preparing prlctl command: %s", err)
state.Put("error", err)

View File

@ -10,6 +10,7 @@ import (
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
const KeyLeftShift uint32 = 0xFFE1
@ -35,7 +36,7 @@ type StepTypeBootCommand struct {
BootCommand []string
HostInterfaces []string
VMName string
Tpl *packer.ConfigTemplate
Ctx interpolate.Context
}
func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction {
@ -61,7 +62,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
ui.Say(fmt.Sprintf("Host IP for the Parallels machine: %s", hostIp))
tplData := &bootCommandTemplateData{
s.Ctx.Data = &bootCommandTemplateData{
hostIp,
httpPort,
s.VMName,
@ -69,7 +70,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction
ui.Say("Typing the boot command...")
for _, command := range s.BootCommand {
command, err := s.Tpl.Process(command, tplData)
command, err := interpolate.Render(command, &s.Ctx)
if err != nil {
err := fmt.Errorf("Error preparing boot command: %s", err)
state.Put("error", err)

View File

@ -2,10 +2,12 @@ package common
import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"os"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
// This step uploads the Parallels Tools ISO to the virtual machine.
@ -25,7 +27,7 @@ type StepUploadParallelsTools struct {
ParallelsToolsFlavor string
ParallelsToolsGuestPath string
ParallelsToolsMode string
Tpl *packer.ConfigTemplate
Ctx interpolate.Context
}
func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepAction {
@ -48,11 +50,11 @@ func (s *StepUploadParallelsTools) Run(state multistep.StateBag) multistep.StepA
}
defer f.Close()
tplData := &toolsPathTemplate{
s.Ctx.Data = &toolsPathTemplate{
Flavor: s.ParallelsToolsFlavor,
}
s.ParallelsToolsGuestPath, err = s.Tpl.Process(s.ParallelsToolsGuestPath, tplData)
s.ParallelsToolsGuestPath, err = interpolate.Render(s.ParallelsToolsGuestPath, &s.Ctx)
if err != nil {
err := fmt.Errorf("Error preparing Parallels Tools path: %s", err)
state.Put("error", err)

View File

@ -3,8 +3,8 @@ package common
import (
"errors"
"fmt"
"github.com/mitchellh/packer/packer"
"text/template"
"github.com/mitchellh/packer/template/interpolate"
)
// These are the different valid mode values for "parallels_tools_mode" which
@ -21,7 +21,7 @@ type ToolsConfig struct {
ParallelsToolsMode string `mapstructure:"parallels_tools_mode"`
}
func (c *ToolsConfig) Prepare(t *packer.ConfigTemplate) []error {
func (c *ToolsConfig) Prepare(ctx *interpolate.Context) []error {
if c.ParallelsToolsMode == "" {
c.ParallelsToolsMode = ParallelsToolsModeUpload
}
@ -30,24 +30,6 @@ func (c *ToolsConfig) Prepare(t *packer.ConfigTemplate) []error {
c.ParallelsToolsGuestPath = "prl-tools-{{.Flavor}}.iso"
}
templates := map[string]*string{
"parallels_tools_flavor": &c.ParallelsToolsFlavor,
"parallels_tools_mode": &c.ParallelsToolsMode,
}
var err error
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))
}
}
if _, err := template.New("path").Parse(c.ParallelsToolsGuestPath); err != nil {
errs = append(errs, fmt.Errorf("parallels_tools_guest_path invalid: %s", err))
}
validMode := false
validModes := []string{
ParallelsToolsModeDisable,
@ -62,6 +44,7 @@ func (c *ToolsConfig) Prepare(t *packer.ConfigTemplate) []error {
}
}
var errs []error
if !validMode {
errs = append(errs,
fmt.Errorf("parallels_tools_mode is invalid. Must be one of: %v",

View File

@ -3,22 +3,25 @@ package iso
import (
"errors"
"fmt"
"log"
"strings"
"github.com/mitchellh/multistep"
parallelscommon "github.com/mitchellh/packer/builder/parallels/common"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"log"
"strings"
"github.com/mitchellh/packer/template/interpolate"
)
const BuilderId = "rickard-von-essen.parallels"
type Builder struct {
config config
config Config
runner multistep.Runner
}
type config struct {
type Config struct {
common.PackerConfig `mapstructure:",squash"`
parallelscommon.FloppyConfig `mapstructure:",squash"`
parallelscommon.OutputConfig `mapstructure:",squash"`
@ -48,33 +51,35 @@ type config struct {
GuestOSDistribution string `mapstructure:"guest_os_distribution"`
ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"`
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",
"prlctl",
"parallel_tools_guest_path",
},
},
}, raws...)
if err != nil {
return nil, err
}
b.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return nil, err
}
b.config.tpl.UserVars = b.config.PackerUserVars
// Accumulate any errors and warnings
errs := common.CheckUnusedConfig(md)
errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(b.config.tpl)...)
var errs *packer.MultiError
errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(
errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...)
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.PrlctlConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.PrlctlVersionConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(b.config.tpl)...)
errs, b.config.OutputConfig.Prepare(&b.config.ctx, &b.config.PackerConfig)...)
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.PrlctlConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.PrlctlVersionConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(&b.config.ctx)...)
warnings := make([]string, 0)
if b.config.DiskSize == 0 {
@ -116,42 +121,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName)
}
// Errors
templates := map[string]*string{
"guest_os_type": &b.config.GuestOSType,
"hard_drive_interface": &b.config.HardDriveInterface,
"http_directory": &b.config.HTTPDir,
"iso_checksum": &b.config.ISOChecksum,
"iso_checksum_type": &b.config.ISOChecksumType,
"iso_url": &b.config.RawSingleISOUrl,
"vm_name": &b.config.VMName,
}
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))
}
}
if b.config.HardDriveInterface != "ide" && b.config.HardDriveInterface != "sata" && b.config.HardDriveInterface != "scsi" {
errs = packer.MultiErrorAppend(
errs, errors.New("hard_drive_interface can only be ide, sata, or scsi"))
@ -264,7 +233,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
new(parallelscommon.StepAttachFloppy),
&parallelscommon.StepPrlctl{
Commands: b.config.Prlctl,
Tpl: b.config.tpl,
Ctx: b.config.ctx,
},
&parallelscommon.StepRun{
BootWait: b.config.BootWait,
@ -274,7 +243,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
BootCommand: b.config.BootCommand,
HostInterfaces: b.config.HostInterfaces,
VMName: b.config.VMName,
Tpl: b.config.tpl,
Ctx: b.config.ctx,
},
&common.StepConnectSSH{
SSHAddress: parallelscommon.SSHAddress,
@ -288,7 +257,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
ParallelsToolsFlavor: b.config.ParallelsToolsFlavor,
ParallelsToolsGuestPath: b.config.ParallelsToolsGuestPath,
ParallelsToolsMode: b.config.ParallelsToolsMode,
Tpl: b.config.tpl,
Ctx: b.config.ctx,
},
new(common.StepProvision),
&parallelscommon.StepShutdown{

View File

@ -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").(parallelscommon.Driver)
ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string)

View File

@ -18,7 +18,7 @@ type stepCreateVM struct {
func (s *stepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*config)
config := state.Get("config").(*Config)
driver := state.Get("driver").(parallelscommon.Driver)
ui := state.Get("ui").(packer.Ui)
name := config.VMName

View File

@ -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