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