github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/cloudstack/config.go (about)

     1  package cloudstack
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/hashicorp/packer/common"
    10  	"github.com/hashicorp/packer/common/uuid"
    11  	"github.com/hashicorp/packer/helper/communicator"
    12  	"github.com/hashicorp/packer/helper/config"
    13  	"github.com/hashicorp/packer/packer"
    14  	"github.com/hashicorp/packer/template/interpolate"
    15  )
    16  
    17  // Config holds all the details needed to configure the builder.
    18  type Config struct {
    19  	common.PackerConfig `mapstructure:",squash"`
    20  	common.HTTPConfig   `mapstructure:",squash"`
    21  	Comm                communicator.Config `mapstructure:",squash"`
    22  
    23  	APIURL       string        `mapstructure:"api_url"`
    24  	APIKey       string        `mapstructure:"api_key"`
    25  	SecretKey    string        `mapstructure:"secret_key"`
    26  	AsyncTimeout time.Duration `mapstructure:"async_timeout"`
    27  	HTTPGetOnly  bool          `mapstructure:"http_get_only"`
    28  	SSLNoVerify  bool          `mapstructure:"ssl_no_verify"`
    29  
    30  	CIDRList             []string `mapstructure:"cidr_list"`
    31  	CreateSecurityGroup  bool     `mapstructure:"create_security_group"`
    32  	DiskOffering         string   `mapstructure:"disk_offering"`
    33  	DiskSize             int64    `mapstructure:"disk_size"`
    34  	Expunge              bool     `mapstructure:"expunge"`
    35  	Hypervisor           string   `mapstructure:"hypervisor"`
    36  	InstanceName         string   `mapstructure:"instance_name"`
    37  	Keypair              string   `mapstructure:"keypair"`
    38  	Network              string   `mapstructure:"network"`
    39  	Project              string   `mapstructure:"project"`
    40  	PublicIPAddress      string   `mapstructure:"public_ip_address"`
    41  	SecurityGroups       []string `mapstructure:"security_groups"`
    42  	ServiceOffering      string   `mapstructure:"service_offering"`
    43  	SourceISO            string   `mapstructure:"source_iso"`
    44  	SourceTemplate       string   `mapstructure:"source_template"`
    45  	TemporaryKeypairName string   `mapstructure:"temporary_keypair_name"`
    46  	UseLocalIPAddress    bool     `mapstructure:"use_local_ip_address"`
    47  	UserData             string   `mapstructure:"user_data"`
    48  	UserDataFile         string   `mapstructure:"user_data_file"`
    49  	Zone                 string   `mapstructure:"zone"`
    50  
    51  	TemplateName            string `mapstructure:"template_name"`
    52  	TemplateDisplayText     string `mapstructure:"template_display_text"`
    53  	TemplateOS              string `mapstructure:"template_os"`
    54  	TemplateFeatured        bool   `mapstructure:"template_featured"`
    55  	TemplatePublic          bool   `mapstructure:"template_public"`
    56  	TemplatePasswordEnabled bool   `mapstructure:"template_password_enabled"`
    57  	TemplateRequiresHVM     bool   `mapstructure:"template_requires_hvm"`
    58  	TemplateScalable        bool   `mapstructure:"template_scalable"`
    59  	TemplateTag             string `mapstructure:"template_tag"`
    60  
    61  	ctx interpolate.Context
    62  }
    63  
    64  // NewConfig parses and validates the given config.
    65  func NewConfig(raws ...interface{}) (*Config, error) {
    66  	c := new(Config)
    67  	err := config.Decode(c, &config.DecodeOpts{
    68  		Interpolate:        true,
    69  		InterpolateContext: &c.ctx,
    70  		InterpolateFilter: &interpolate.RenderFilter{
    71  			Exclude: []string{
    72  				"user_data",
    73  			},
    74  		},
    75  	}, raws...)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	var errs *packer.MultiError
    81  
    82  	// Set some defaults.
    83  	if c.APIURL == "" {
    84  		// Default to environment variable for api_url, if it exists
    85  		c.APIURL = os.Getenv("CLOUDSTACK_API_URL")
    86  	}
    87  
    88  	if c.APIKey == "" {
    89  		// Default to environment variable for api_key, if it exists
    90  		c.APIKey = os.Getenv("CLOUDSTACK_API_KEY")
    91  	}
    92  
    93  	if c.SecretKey == "" {
    94  		// Default to environment variable for secret_key, if it exists
    95  		c.SecretKey = os.Getenv("CLOUDSTACK_SECRET_KEY")
    96  	}
    97  
    98  	if c.AsyncTimeout == 0 {
    99  		c.AsyncTimeout = 30 * time.Minute
   100  	}
   101  
   102  	if len(c.CIDRList) == 0 {
   103  		c.CIDRList = []string{"0.0.0.0/0"}
   104  	}
   105  
   106  	if c.InstanceName == "" {
   107  		c.InstanceName = fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
   108  	}
   109  
   110  	if c.TemplateName == "" {
   111  		name, err := interpolate.Render("packer-{{timestamp}}", nil)
   112  		if err != nil {
   113  			errs = packer.MultiErrorAppend(errs,
   114  				fmt.Errorf("Unable to parse template name: %s ", err))
   115  		}
   116  
   117  		c.TemplateName = name
   118  	}
   119  
   120  	if c.TemplateDisplayText == "" {
   121  		c.TemplateDisplayText = c.TemplateName
   122  	}
   123  
   124  	// If we are not given an explicit keypair, ssh_password or ssh_private_key_file,
   125  	// then create a temporary one, but only if the temporary_keypair_name has not
   126  	// been provided.
   127  	if c.Keypair == "" && c.TemporaryKeypairName == "" &&
   128  		c.Comm.SSHPrivateKey == "" && c.Comm.SSHPassword == "" {
   129  		c.TemporaryKeypairName = fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID())
   130  	}
   131  
   132  	// Process required parameters.
   133  	if c.APIURL == "" {
   134  		errs = packer.MultiErrorAppend(errs, errors.New("a api_url must be specified"))
   135  	}
   136  
   137  	if c.APIKey == "" {
   138  		errs = packer.MultiErrorAppend(errs, errors.New("a api_key must be specified"))
   139  	}
   140  
   141  	if c.SecretKey == "" {
   142  		errs = packer.MultiErrorAppend(errs, errors.New("a secret_key must be specified"))
   143  	}
   144  
   145  	if c.Network == "" {
   146  		errs = packer.MultiErrorAppend(errs, errors.New("a network must be specified"))
   147  	}
   148  
   149  	if c.CreateSecurityGroup && !c.Expunge {
   150  		errs = packer.MultiErrorAppend(errs, errors.New("auto creating a temporary security group requires expunge"))
   151  	}
   152  
   153  	if c.ServiceOffering == "" {
   154  		errs = packer.MultiErrorAppend(errs, errors.New("a service_offering must be specified"))
   155  	}
   156  
   157  	if c.SourceISO == "" && c.SourceTemplate == "" {
   158  		errs = packer.MultiErrorAppend(
   159  			errs, errors.New("either source_iso or source_template must be specified"))
   160  	}
   161  
   162  	if c.SourceISO != "" && c.SourceTemplate != "" {
   163  		errs = packer.MultiErrorAppend(
   164  			errs, errors.New("only one of source_iso or source_template can be specified"))
   165  	}
   166  
   167  	if c.SourceISO != "" && c.DiskOffering == "" {
   168  		errs = packer.MultiErrorAppend(
   169  			errs, errors.New("a disk_offering must be specified when using source_iso"))
   170  	}
   171  
   172  	if c.SourceISO != "" && c.Hypervisor == "" {
   173  		errs = packer.MultiErrorAppend(
   174  			errs, errors.New("a hypervisor must be specified when using source_iso"))
   175  	}
   176  
   177  	if c.TemplateOS == "" {
   178  		errs = packer.MultiErrorAppend(errs, errors.New("a template_os must be specified"))
   179  	}
   180  
   181  	if c.UserData != "" && c.UserDataFile != "" {
   182  		errs = packer.MultiErrorAppend(
   183  			errs, errors.New("only one of user_data or user_data_file can be specified"))
   184  	}
   185  
   186  	if c.UserDataFile != "" {
   187  		if _, err := os.Stat(c.UserDataFile); err != nil {
   188  			errs = packer.MultiErrorAppend(
   189  				errs, fmt.Errorf("user_data_file not found: %s", c.UserDataFile))
   190  		}
   191  	}
   192  
   193  	if c.Zone == "" {
   194  		errs = packer.MultiErrorAppend(errs, errors.New("a zone must be specified"))
   195  	}
   196  
   197  	if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
   198  		errs = packer.MultiErrorAppend(errs, es...)
   199  	}
   200  
   201  	// Check for errors and return if we have any.
   202  	if errs != nil && len(errs.Errors) > 0 {
   203  		return nil, errs
   204  	}
   205  
   206  	return c, nil
   207  }