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  }