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 }