github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/builder/cloudstack/config.go (about) 1 package cloudstack 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "time" 8 9 "github.com/mitchellh/packer/common" 10 "github.com/mitchellh/packer/common/uuid" 11 "github.com/mitchellh/packer/helper/communicator" 12 "github.com/mitchellh/packer/helper/config" 13 "github.com/mitchellh/packer/packer" 14 "github.com/mitchellh/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 Comm communicator.Config `mapstructure:",squash"` 21 22 APIURL string `mapstructure:"api_url"` 23 APIKey string `mapstructure:"api_key"` 24 SecretKey string `mapstructure:"secret_key"` 25 AsyncTimeout time.Duration `mapstructure:"async_timeout"` 26 HTTPGetOnly bool `mapstructure:"http_get_only"` 27 SSLNoVerify bool `mapstructure:"ssl_no_verify"` 28 29 DiskOffering string `mapstructure:"disk_offering"` 30 DiskSize int64 `mapstructure:"disk_size"` 31 CIDRList []string `mapstructure:"cidr_list"` 32 Hypervisor string `mapstructure:"hypervisor"` 33 InstanceName string `mapstructure:"instance_name"` 34 Keypair string `mapstructure:"keypair"` 35 Network string `mapstructure:"network"` 36 Project string `mapstructure:"project"` 37 PublicIPAddress string `mapstructure:"public_ip_address"` 38 ServiceOffering string `mapstructure:"service_offering"` 39 SourceTemplate string `mapstructure:"source_template"` 40 SourceISO string `mapstructure:"source_iso"` 41 UserData string `mapstructure:"user_data"` 42 UserDataFile string `mapstructure:"user_data_file"` 43 UseLocalIPAddress bool `mapstructure:"use_local_ip_address"` 44 Zone string `mapstructure:"zone"` 45 46 TemplateName string `mapstructure:"template_name"` 47 TemplateDisplayText string `mapstructure:"template_display_text"` 48 TemplateOS string `mapstructure:"template_os"` 49 TemplateFeatured bool `mapstructure:"template_featured"` 50 TemplatePublic bool `mapstructure:"template_public"` 51 TemplatePasswordEnabled bool `mapstructure:"template_password_enabled"` 52 TemplateRequiresHVM bool `mapstructure:"template_requires_hvm"` 53 TemplateScalable bool `mapstructure:"template_scalable"` 54 TemplateTag string `mapstructure:"template_tag"` 55 56 ctx interpolate.Context 57 hostAddress string // The host address used by the communicators. 58 instanceSource string // This can be either a template ID or an ISO ID. 59 } 60 61 // NewConfig parses and validates the given config. 62 func NewConfig(raws ...interface{}) (*Config, error) { 63 c := new(Config) 64 err := config.Decode(c, &config.DecodeOpts{ 65 Interpolate: true, 66 InterpolateContext: &c.ctx, 67 }, raws...) 68 if err != nil { 69 return nil, err 70 } 71 72 var errs *packer.MultiError 73 74 // Set some defaults. 75 if c.AsyncTimeout == 0 { 76 c.AsyncTimeout = 30 * time.Minute 77 } 78 79 if c.InstanceName == "" { 80 c.InstanceName = fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID()) 81 } 82 83 if c.TemplateName == "" { 84 name, err := interpolate.Render("packer-{{timestamp}}", nil) 85 if err != nil { 86 errs = packer.MultiErrorAppend(errs, 87 fmt.Errorf("Unable to parse template name: %s ", err)) 88 } 89 90 c.TemplateName = name 91 } 92 93 if c.TemplateDisplayText == "" { 94 c.TemplateDisplayText = c.TemplateName 95 } 96 97 // Process required parameters. 98 if c.APIURL == "" { 99 errs = packer.MultiErrorAppend(errs, errors.New("a api_url must be specified")) 100 } 101 102 if c.APIKey == "" { 103 errs = packer.MultiErrorAppend(errs, errors.New("a api_key must be specified")) 104 } 105 106 if c.SecretKey == "" { 107 errs = packer.MultiErrorAppend(errs, errors.New("a secret_key must be specified")) 108 } 109 110 if len(c.CIDRList) == 0 && !c.UseLocalIPAddress { 111 errs = packer.MultiErrorAppend(errs, errors.New("a cidr_list must be specified")) 112 } 113 114 if c.Network == "" { 115 errs = packer.MultiErrorAppend(errs, errors.New("a network must be specified")) 116 } 117 118 if c.ServiceOffering == "" { 119 errs = packer.MultiErrorAppend(errs, errors.New("a service_offering must be specified")) 120 } 121 122 if c.SourceISO == "" && c.SourceTemplate == "" { 123 errs = packer.MultiErrorAppend( 124 errs, errors.New("either source_iso or source_template must be specified")) 125 } 126 127 if c.SourceISO != "" && c.SourceTemplate != "" { 128 errs = packer.MultiErrorAppend( 129 errs, errors.New("only one of source_iso or source_template can be specified")) 130 } 131 132 if c.SourceISO != "" && c.DiskOffering == "" { 133 errs = packer.MultiErrorAppend( 134 errs, errors.New("a disk_offering must be specified when using source_iso")) 135 } 136 137 if c.SourceISO != "" && c.Hypervisor == "" { 138 errs = packer.MultiErrorAppend( 139 errs, errors.New("a hypervisor must be specified when using source_iso")) 140 } 141 142 if c.TemplateOS == "" { 143 errs = packer.MultiErrorAppend(errs, errors.New("a template_os must be specified")) 144 } 145 146 if c.UserData != "" && c.UserDataFile != "" { 147 errs = packer.MultiErrorAppend( 148 errs, errors.New("only one of user_data or user_data_file can be specified")) 149 } 150 151 if c.UserDataFile != "" { 152 if _, err := os.Stat(c.UserDataFile); err != nil { 153 errs = packer.MultiErrorAppend( 154 errs, fmt.Errorf("user_data_file not found: %s", c.UserDataFile)) 155 } 156 } 157 158 if c.Zone == "" { 159 errs = packer.MultiErrorAppend(errs, errors.New("a zone must be specified")) 160 } 161 162 if es := c.Comm.Prepare(&c.ctx); len(es) > 0 { 163 errs = packer.MultiErrorAppend(errs, es...) 164 } 165 166 // Check for errors and return if we have any. 167 if errs != nil && len(errs.Errors) > 0 { 168 return nil, errs 169 } 170 171 return c, nil 172 }