Merge pull request #768 from devcamcar/openstack-env-support
builder/openstack: Add support for standard OpenStack environment variables
This commit is contained in:
commit
159587daf4
|
@ -2,17 +2,20 @@ package openstack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/mitchellh/packer/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"github.com/rackspace/gophercloud"
|
"github.com/rackspace/gophercloud"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccessConfig is for common configuration related to openstack access
|
// AccessConfig is for common configuration related to openstack access
|
||||||
type AccessConfig struct {
|
type AccessConfig struct {
|
||||||
Username string `mapstructure:"username"`
|
Username string `mapstructure:"username"`
|
||||||
Password string `mapstructure:"password"`
|
Password string `mapstructure:"password"`
|
||||||
|
ApiKey string `mapstructure:"api_key"`
|
||||||
Project string `mapstructure:"project"`
|
Project string `mapstructure:"project"`
|
||||||
Provider string `mapstructure:"provider"`
|
Provider string `mapstructure:"provider"`
|
||||||
RawRegion string `mapstructure:"region"`
|
RawRegion string `mapstructure:"region"`
|
||||||
|
@ -22,39 +25,35 @@ type AccessConfig struct {
|
||||||
// Auth returns a valid Auth object for access to openstack services, or
|
// Auth returns a valid Auth object for access to openstack services, or
|
||||||
// an error if the authentication couldn't be resolved.
|
// an error if the authentication couldn't be resolved.
|
||||||
func (c *AccessConfig) Auth() (gophercloud.AccessProvider, error) {
|
func (c *AccessConfig) Auth() (gophercloud.AccessProvider, error) {
|
||||||
username := c.Username
|
c.Username = common.CoalesceVals(c.Username, os.Getenv("SDK_USERNAME"), os.Getenv("OS_USERNAME"))
|
||||||
password := c.Password
|
c.Password = common.CoalesceVals(c.Password, os.Getenv("SDK_PASSWORD"), os.Getenv("OS_PASSWORD"))
|
||||||
project := c.Project
|
c.ApiKey = common.CoalesceVals(c.ApiKey, os.Getenv("SDK_API_KEY"))
|
||||||
provider := c.Provider
|
c.Project = common.CoalesceVals(c.Project, os.Getenv("SDK_PROJECT"), os.Getenv("OS_TENANT_NAME"))
|
||||||
proxy := c.ProxyUrl
|
c.Provider = common.CoalesceVals(c.Provider, os.Getenv("SDK_PROVIDER"), os.Getenv("OS_AUTH_URL"))
|
||||||
|
c.RawRegion = common.CoalesceVals(c.RawRegion, os.Getenv("SDK_REGION"), os.Getenv("OS_REGION_NAME"))
|
||||||
|
|
||||||
if username == "" {
|
// OpenStack's auto-generated openrc.sh files do not append the suffix
|
||||||
username = os.Getenv("SDK_USERNAME")
|
// /tokens to the authentication URL. This ensures it is present when
|
||||||
}
|
// specifying the URL.
|
||||||
if password == "" {
|
if strings.Contains(c.Provider, "://") && !strings.HasSuffix(c.Provider, "/tokens") {
|
||||||
password = os.Getenv("SDK_PASSWORD")
|
c.Provider += "/tokens"
|
||||||
}
|
|
||||||
if project == "" {
|
|
||||||
project = os.Getenv("SDK_PROJECT")
|
|
||||||
}
|
|
||||||
if provider == "" {
|
|
||||||
provider = os.Getenv("SDK_PROVIDER")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
authoptions := gophercloud.AuthOptions{
|
authoptions := gophercloud.AuthOptions{
|
||||||
Username: username,
|
Username: c.Username,
|
||||||
Password: password,
|
Password: c.Password,
|
||||||
|
ApiKey: c.ApiKey,
|
||||||
AllowReauth: true,
|
AllowReauth: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
if project != "" {
|
if c.Project != "" {
|
||||||
authoptions.TenantName = project
|
authoptions.TenantName = c.Project
|
||||||
}
|
}
|
||||||
|
|
||||||
// For corporate networks it may be the case where we want our API calls
|
// For corporate networks it may be the case where we want our API calls
|
||||||
// to be sent through a separate HTTP proxy than external traffic.
|
// to be sent through a separate HTTP proxy than external traffic.
|
||||||
if proxy != "" {
|
if c.ProxyUrl != "" {
|
||||||
url, err := url.Parse(proxy)
|
url, err := url.Parse(c.ProxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -64,11 +63,11 @@ func (c *AccessConfig) Auth() (gophercloud.AccessProvider, error) {
|
||||||
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(url)}
|
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(url)}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gophercloud.Authenticate(provider, authoptions)
|
return gophercloud.Authenticate(c.Provider, authoptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AccessConfig) Region() string {
|
func (c *AccessConfig) Region() string {
|
||||||
return c.RawRegion
|
return common.CoalesceVals(c.RawRegion, os.Getenv("SDK_REGION"), os.Getenv("OS_REGION_NAME"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
|
func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
|
@ -83,6 +82,7 @@ func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
templates := map[string]*string{
|
templates := map[string]*string{
|
||||||
"username": &c.Username,
|
"username": &c.Username,
|
||||||
"password": &c.Password,
|
"password": &c.Password,
|
||||||
|
"apiKey": &c.ApiKey,
|
||||||
"provider": &c.Provider,
|
"provider": &c.Provider,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.RawRegion == "" {
|
if c.Region() == "" {
|
||||||
errs = append(errs, fmt.Errorf("region must be specified"))
|
errs = append(errs, fmt.Errorf("region must be specified"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,3 +194,12 @@ func decodeConfigHook(raws []interface{}) (mapstructure.DecodeHookFunc, error) {
|
||||||
return v, nil
|
return v, nil
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CoalesceVals(vals ...string) string {
|
||||||
|
for _, el := range vals {
|
||||||
|
if el != "" {
|
||||||
|
return el
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue