github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/builder/virtualbox/ovf/config.go (about)

     1  package ovf
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  
     8  	vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common"
     9  	"github.com/mitchellh/packer/common"
    10  	"github.com/mitchellh/packer/packer"
    11  )
    12  
    13  // Config is the configuration structure for the builder.
    14  type Config struct {
    15  	common.PackerConfig             `mapstructure:",squash"`
    16  	vboxcommon.ExportConfig         `mapstructure:",squash"`
    17  	vboxcommon.ExportOpts           `mapstructure:",squash"`
    18  	vboxcommon.FloppyConfig         `mapstructure:",squash"`
    19  	vboxcommon.OutputConfig         `mapstructure:",squash"`
    20  	vboxcommon.RunConfig            `mapstructure:",squash"`
    21  	vboxcommon.SSHConfig            `mapstructure:",squash"`
    22  	vboxcommon.ShutdownConfig       `mapstructure:",squash"`
    23  	vboxcommon.VBoxManageConfig     `mapstructure:",squash"`
    24  	vboxcommon.VBoxManagePostConfig `mapstructure:",squash"`
    25  	vboxcommon.VBoxVersionConfig    `mapstructure:",squash"`
    26  
    27  	BootCommand          []string `mapstructure:"boot_command"`
    28  	SourcePath           string   `mapstructure:"source_path"`
    29  	GuestAdditionsMode   string   `mapstructure:"guest_additions_mode"`
    30  	GuestAdditionsPath   string   `mapstructure:"guest_additions_path"`
    31  	GuestAdditionsURL    string   `mapstructure:"guest_additions_url"`
    32  	GuestAdditionsSHA256 string   `mapstructure:"guest_additions_sha256"`
    33  	VMName               string   `mapstructure:"vm_name"`
    34  	ImportOpts           string   `mapstructure:"import_opts"`
    35  	ImportFlags          []string `mapstructure:"import_flags"`
    36  
    37  	tpl *packer.ConfigTemplate
    38  }
    39  
    40  func NewConfig(raws ...interface{}) (*Config, []string, error) {
    41  	c := new(Config)
    42  	md, err := common.DecodeConfig(c, raws...)
    43  	if err != nil {
    44  		return nil, nil, err
    45  	}
    46  
    47  	c.tpl, err = packer.NewConfigTemplate()
    48  	if err != nil {
    49  		return nil, nil, err
    50  	}
    51  	c.tpl.UserVars = c.PackerUserVars
    52  
    53  	// Defaults
    54  	if c.GuestAdditionsMode == "" {
    55  		c.GuestAdditionsMode = "upload"
    56  	}
    57  
    58  	if c.GuestAdditionsPath == "" {
    59  		c.GuestAdditionsPath = "VBoxGuestAdditions.iso"
    60  	}
    61  	if c.VMName == "" {
    62  		c.VMName = fmt.Sprintf("packer-%s-{{timestamp}}", c.PackerBuildName)
    63  	}
    64  
    65  	// Prepare the errors
    66  	errs := common.CheckUnusedConfig(md)
    67  	errs = packer.MultiErrorAppend(errs, c.ExportConfig.Prepare(c.tpl)...)
    68  	errs = packer.MultiErrorAppend(errs, c.ExportOpts.Prepare(c.tpl)...)
    69  	errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(c.tpl)...)
    70  	errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(c.tpl, &c.PackerConfig)...)
    71  	errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...)
    72  	errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(c.tpl)...)
    73  	errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(c.tpl)...)
    74  	errs = packer.MultiErrorAppend(errs, c.VBoxManageConfig.Prepare(c.tpl)...)
    75  	errs = packer.MultiErrorAppend(errs, c.VBoxManagePostConfig.Prepare(c.tpl)...)
    76  	errs = packer.MultiErrorAppend(errs, c.VBoxVersionConfig.Prepare(c.tpl)...)
    77  
    78  	templates := map[string]*string{
    79  		"guest_additions_mode":   &c.GuestAdditionsMode,
    80  		"guest_additions_sha256": &c.GuestAdditionsSHA256,
    81  		"source_path":            &c.SourcePath,
    82  		"vm_name":                &c.VMName,
    83  		"import_opts":            &c.ImportOpts,
    84  	}
    85  
    86  	for n, ptr := range templates {
    87  		var err error
    88  		*ptr, err = c.tpl.Process(*ptr, nil)
    89  		if err != nil {
    90  			errs = packer.MultiErrorAppend(
    91  				errs, fmt.Errorf("Error processing %s: %s", n, err))
    92  		}
    93  	}
    94  
    95  	sliceTemplates := map[string][]string{
    96  		"import_flags": c.ImportFlags,
    97  	}
    98  
    99  	for n, slice := range sliceTemplates {
   100  		for i, elem := range slice {
   101  			var err error
   102  			slice[i], err = c.tpl.Process(elem, nil)
   103  			if err != nil {
   104  				errs = packer.MultiErrorAppend(
   105  					errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err))
   106  			}
   107  		}
   108  	}
   109  
   110  	if c.SourcePath == "" {
   111  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required"))
   112  	} else {
   113  		if _, err := os.Stat(c.SourcePath); err != nil {
   114  			errs = packer.MultiErrorAppend(errs,
   115  				fmt.Errorf("source_path is invalid: %s", err))
   116  		}
   117  	}
   118  
   119  	for i, command := range c.BootCommand {
   120  		if err := c.tpl.Validate(command); err != nil {
   121  			errs = packer.MultiErrorAppend(errs,
   122  				fmt.Errorf("Error processing boot_command[%d]: %s", i, err))
   123  		}
   124  	}
   125  
   126  	validates := map[string]*string{
   127  		"guest_additions_path": &c.GuestAdditionsPath,
   128  		"guest_additions_url":  &c.GuestAdditionsURL,
   129  	}
   130  
   131  	for n, ptr := range validates {
   132  		if err := c.tpl.Validate(*ptr); err != nil {
   133  			errs = packer.MultiErrorAppend(
   134  				errs, fmt.Errorf("Error parsing %s: %s", n, err))
   135  		}
   136  	}
   137  
   138  	validMode := false
   139  	validModes := []string{
   140  		vboxcommon.GuestAdditionsModeDisable,
   141  		vboxcommon.GuestAdditionsModeAttach,
   142  		vboxcommon.GuestAdditionsModeUpload,
   143  	}
   144  
   145  	for _, mode := range validModes {
   146  		if c.GuestAdditionsMode == mode {
   147  			validMode = true
   148  			break
   149  		}
   150  	}
   151  
   152  	if !validMode {
   153  		errs = packer.MultiErrorAppend(errs,
   154  			fmt.Errorf("guest_additions_mode is invalid. Must be one of: %v", validModes))
   155  	}
   156  
   157  	if c.GuestAdditionsSHA256 != "" {
   158  		c.GuestAdditionsSHA256 = strings.ToLower(c.GuestAdditionsSHA256)
   159  	}
   160  
   161  	// Warnings
   162  	var warnings []string
   163  	if c.ShutdownCommand == "" {
   164  		warnings = append(warnings,
   165  			"A shutdown_command was not specified. Without a shutdown command, Packer\n"+
   166  				"will forcibly halt the virtual machine, which may result in data loss.")
   167  	}
   168  
   169  	// Check for any errors.
   170  	if errs != nil && len(errs.Errors) > 0 {
   171  		return nil, warnings, errs
   172  	}
   173  
   174  	// TODO: Write a packer fix and just remove import_opts
   175  	if c.ImportOpts != "" {
   176  		c.ImportFlags = append(c.ImportFlags, "--options", c.ImportOpts)
   177  	}
   178  
   179  	return c, warnings, nil
   180  }