github.com/daniellockard/packer@v0.7.6-0.20141210173435-5a9390934716/builder/openstack/access_config.go (about) 1 package openstack 2 3 import ( 4 "crypto/tls" 5 "fmt" 6 "github.com/mitchellh/packer/common" 7 "github.com/mitchellh/packer/packer" 8 "net/http" 9 "net/url" 10 "os" 11 "strings" 12 13 "github.com/mitchellh/gophercloud-fork-40444fb" 14 ) 15 16 // AccessConfig is for common configuration related to openstack access 17 type AccessConfig struct { 18 Username string `mapstructure:"username"` 19 Password string `mapstructure:"password"` 20 ApiKey string `mapstructure:"api_key"` 21 Project string `mapstructure:"project"` 22 Provider string `mapstructure:"provider"` 23 RawRegion string `mapstructure:"region"` 24 ProxyUrl string `mapstructure:"proxy_url"` 25 TenantId string `mapstructure:"tenant_id"` 26 Insecure bool `mapstructure:"insecure"` 27 } 28 29 // Auth returns a valid Auth object for access to openstack services, or 30 // an error if the authentication couldn't be resolved. 31 func (c *AccessConfig) Auth() (gophercloud.AccessProvider, error) { 32 c.Username = common.ChooseString(c.Username, os.Getenv("SDK_USERNAME"), os.Getenv("OS_USERNAME")) 33 c.Password = common.ChooseString(c.Password, os.Getenv("SDK_PASSWORD"), os.Getenv("OS_PASSWORD")) 34 c.ApiKey = common.ChooseString(c.ApiKey, os.Getenv("SDK_API_KEY")) 35 c.Project = common.ChooseString(c.Project, os.Getenv("SDK_PROJECT"), os.Getenv("OS_TENANT_NAME")) 36 c.Provider = common.ChooseString(c.Provider, os.Getenv("SDK_PROVIDER"), os.Getenv("OS_AUTH_URL")) 37 c.RawRegion = common.ChooseString(c.RawRegion, os.Getenv("SDK_REGION"), os.Getenv("OS_REGION_NAME")) 38 c.TenantId = common.ChooseString(c.TenantId, os.Getenv("OS_TENANT_ID")) 39 40 // OpenStack's auto-generated openrc.sh files do not append the suffix 41 // /tokens to the authentication URL. This ensures it is present when 42 // specifying the URL. 43 if strings.Contains(c.Provider, "://") && !strings.HasSuffix(c.Provider, "/tokens") { 44 c.Provider += "/tokens" 45 } 46 47 authoptions := gophercloud.AuthOptions{ 48 AllowReauth: true, 49 50 ApiKey: c.ApiKey, 51 TenantId: c.TenantId, 52 TenantName: c.Project, 53 Username: c.Username, 54 Password: c.Password, 55 } 56 57 default_transport := &http.Transport{} 58 59 if c.Insecure { 60 cfg := new(tls.Config) 61 cfg.InsecureSkipVerify = true 62 default_transport.TLSClientConfig = cfg 63 } 64 65 // For corporate networks it may be the case where we want our API calls 66 // to be sent through a separate HTTP proxy than external traffic. 67 if c.ProxyUrl != "" { 68 url, err := url.Parse(c.ProxyUrl) 69 if err != nil { 70 return nil, err 71 } 72 73 // The gophercloud.Context has a UseCustomClient method which 74 // would allow us to override with a new instance of http.Client. 75 default_transport.Proxy = http.ProxyURL(url) 76 } 77 78 if c.Insecure || c.ProxyUrl != "" { 79 http.DefaultTransport = default_transport 80 } 81 82 return gophercloud.Authenticate(c.Provider, authoptions) 83 } 84 85 func (c *AccessConfig) Region() string { 86 return common.ChooseString(c.RawRegion, os.Getenv("SDK_REGION"), os.Getenv("OS_REGION_NAME")) 87 } 88 89 func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error { 90 if t == nil { 91 var err error 92 t, err = packer.NewConfigTemplate() 93 if err != nil { 94 return []error{err} 95 } 96 } 97 98 templates := map[string]*string{ 99 "username": &c.Username, 100 "password": &c.Password, 101 "api_key": &c.ApiKey, 102 "provider": &c.Provider, 103 "project": &c.Project, 104 "tenant_id": &c.TenantId, 105 "region": &c.RawRegion, 106 "proxy_url": &c.ProxyUrl, 107 } 108 109 errs := make([]error, 0) 110 for n, ptr := range templates { 111 var err error 112 *ptr, err = t.Process(*ptr, nil) 113 if err != nil { 114 errs = append( 115 errs, fmt.Errorf("Error processing %s: %s", n, err)) 116 } 117 } 118 119 if strings.HasPrefix(c.Provider, "rackspace") { 120 if c.Region() == "" { 121 errs = append(errs, fmt.Errorf("region must be specified when using rackspace")) 122 } 123 } 124 125 if len(errs) > 0 { 126 return errs 127 } 128 129 return nil 130 }